UVA 1252 - Twenty Questions(状态压缩DP+记忆化搜索)

题意: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));
    }
}



你可能感兴趣的:(UVA 1252 - Twenty Questions(状态压缩DP+记忆化搜索))