题意:01特征串组成的物品,现在你可以询问一个位置的特征,对于每个东西如果为1回答YES,如果为0回答NO。那么如果你当前无法区分开每个东西,就可以继续问一个特征,现在要求最坏情况下,你需要询问几次的最少次数。
思路:枚举询问的位置的所有可能,也就是枚举(1<<m)-1的所有子集,每次询问下一个特征就枚举询问的所有可能,所以会产生重复的子集,所以用记忆化,而且状态仅仅是询问过的特征集合还不够,没办法判断当前的询问是否可以区分开某个物体,所以还要枚举当前询问的特征有或者没有,所以就是枚举特征询问子集的子集,所以状态数接近3^n,每个状态决策m次
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int m,n;
int st[130];
int dp[1<<11][1<<11];
const int inf = 0x3f3f3f3f;
int DP(int s1,int s2)
{
int &ans=dp[s1][s2];
if(ans>=0) return ans;
ans=inf;
int cnt=0;
for(int i=1;i<=n;i++)
if((s1&st[i])==s2) cnt++;
if(cnt<=1)
return ans=0;
for(int i=0;i<m;i++)
if((s1&(1<<i))==0)
ans=min(ans,max(DP(s1|(1<<i),s2),DP(s1|(1<<i),s2^(1<<i)))+1);
return ans;
}
int main()
{
while(~scanf("%d%d",&m,&n)&&(n||m))
{
for(int i=1;i<=n;i++)
{
char str[15];
int t=0;
scanf("%s",str);
for(int j=0;str[j];j++)
if(str[j]=='1')
t|=(1<<j);
st[i]=t;
}
memset(dp,-1,sizeof(dp));
printf("%d\n",DP(0,0));
}
}