首页 > 代码库 > UVa 1252 - Twenty Questions(记忆化搜索,状态压缩dp)
UVa 1252 - Twenty Questions(记忆化搜索,状态压缩dp)
题目链接:uva 1252
题意:
有n个长度为m的二进制串,每个都是不同的。
为了把所有字符串区分开,你可以询问,每次可以问某位上是0还是1。
问最少提问次数,可以把所有字符串区分开来。
思路来源于:点击打开链接
思路:
m很小,可以考虑状态压缩。
dp[s1][s2]表示询问的状态为s1时,此时能猜到状态包含s2时最小需要的步数。
当询问的几位=s2的二进制串小于2时就能区分出来了,dp[s1][s2]=0;
不能区分则再询问一次,s1|=(1<<k),如果问某位为0,则s2不变,问某位为1,则s2|=(1<<k)。
递归下去就能找到答案了。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #define maxn 1005 #define MAXN 1000005 #define mod 100000000 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 typedef long long ll; using namespace std; int n,m,ans,tot,flag; char s[150][15]; int dp[1<<11][1<<11],mp[150]; int dfs(int s1,int s2) { if(dp[s1][s2]<INF) return dp[s1][s2]; int i,j,t=0; for(i=1;i<=n;i++) { if((mp[i]&s1)==s2) t++; } if(t<=1) { dp[s1][s2]=0; return 0; } int best=INF; for(i=0;i<m;i++) { if(s1&(1<<i)) continue ; best=min(best,max(dfs(s1|(1<<i),s2),dfs(s1|(1<<i),s2|(1<<i)))); } dp[s1][s2]=best+1; return best+1; } int main() { int i,j,t; while(~scanf("%d%d",&m,&n)) { if(m==0&&n==0) break ; for(i=1;i<=n;i++) { scanf("%s",s[i]); mp[i]=0; for(j=0;j<m;j++) { if(s[i][j]=='1') mp[i]|=(1<<j); } } memset(dp,0x3f,sizeof(dp)); ans=dfs(0,0); printf("%d\n",ans); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。