题目大意:有n件物品,每件物品有m个特征,可以对特征进行询问,询问的结果是得知某个物体是否含有该特征,要把所有的物品区分出来(n个物品的特征都互不相同)最小需要多少次询问?

题目分析:定义dp(s,a)表示询问了的特征集合为s,物体含有特征集合a中的所有特征,但不含特征集合 s^a 中的所有特征时还需的最少询问次数。状态转移方程为dp(s,a)=min(max(dp(s|(1<<k),a|(1<<k)),dp(s|(1<<k),a))+1)。 用记忆化搜索的形式实现即可。

当这样的物体只有一个或一个没有时,便可区分出所有的物品,此时dp(s,a)=0。

代码如下:

# include<iostream>
# include<cstdio>
# include<string>
# include<cstring>
# include<algorithm>
using namespace std; const int INF=0x3f3f3f3f; char p[13];
int dp[1<<11][1<<11],sta[130],m,n; int getVal()
{
int res=0;
for(int i=0;i<m;++i)
if(p[i]=='1')
res|=(1<<i);
return res;
} int DP(int s,int a)
{
if(dp[s][a]!=INF)
return dp[s][a]; int num=0;
for(int i=0;i<n;++i)///在这里,也可以预处理出来以提高效率;
if((sta[i]&s)==a)///"=="的优先级比"&"的高!!!
++num;
if(num<=1)
return dp[s][a]=0; int &ans=dp[s][a];
for(int i=0;i<m;++i){
if(s&(1<<i))
continue;
ans=min(ans,max(DP(s|(1<<i),a),DP(s|(1<<i),a|(1<<i)))+1);
}
return ans;
} int main()
{
while(scanf("%d%d",&m,&n)&&n+m)
{
for(int i=0;i<n;++i){
scanf("%s",p);
sta[i]=getVal();
}
memset(dp,INF,sizeof(dp));
printf("%d\n",DP(0,0));
}
return 0;
}

  

最新文章

  1. 在Windows中玩转Docker Toolbox
  2. Node.js + Web Socket 打造即时聊天程序嗨聊
  3. android 的touch event分析
  4. 不是语言之争--Go vs Erlang
  5. php pdo oracle中文乱码
  6. 存储占用:Memory Map 汉化去广告版
  7. 《使用wxWidgets进行跨平台程序开发》chap02——一个简单的应用程序
  8. word-wrap: break-word 和 word-break: break-all 到底有啥区别?
  9. ThreadLocal 在web环境下使用的边界问题
  10. JavaScript引用类型之Object类型
  11. 如何编写更好的SQL查询:终极指南-第一部分
  12. Android SDK下载失败的解决方法
  13. 压力测试Apache
  14. 1038. Jewels And Stones
  15. JAVA虚拟机体系结构JAVA虚拟机的生命周期
  16. Python包下载超时问题解决
  17. cmd命令,bat脚本
  18. Java获取某个月的天数
  19. 如何使input双击时不显示历史记录
  20. oracle查询锁表

热门文章

  1. bzoj1056/1862 [Zjoi2006]GameZ游戏排名系统
  2. Python学习笔记之面向对象编程(三)Python类的魔术方法
  3. 20145304 Exp8 Web基础
  4. linux 之awk命令详解
  5. POJ 2823 Sliding Window(单调队列 || 线段树)题解
  6. 51NOD 1099 任务执行顺序
  7. php跨域
  8. js中拼接HTML方式方法及注意事项
  9. 解决 mininet gave up after 3 retries 问题
  10. UVa 10163 仓库守卫