UVA - 1252 Twenty Questions (状压dp+vis数组加速)
Posted asdfsag
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA - 1252 Twenty Questions (状压dp+vis数组加速)相关的知识,希望对你有一定的参考价值。
有n个物品,每个物品有m个特征。随机选择一个物品让你去猜,你每次可以询问一个特征的答案,问在采取最优策略时,最坏情况下需要猜的次数是多少。
设siz[S]为满足特征性质集合S的特征的物品总数,dp[S]为当前得到的物品特征信息为S的情况下最坏情况下需要猜多少次,则$dp[S]=max{dp(S|(1<<(2*i))),dp(S|(2<<(2*i))}$(为了表示某个特征不确定的状态,需要将集合大小加倍)。dfs预处理siz的复杂度为$O(n*2^m)$,dp的复杂度为$O(m*3^m)$。
这道题我一开始总是迷之TLE,加了很多优化都失败了,后来好不容易才发现原来是memset花的时间太长了,于是把vis数组的值换成了Case的值,这样就可以避免每次都初始化了。然后时间从TLE直降到90ms,巨无语。。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll N=11,inf=0x3f3f3f3f; 5 int siz[(1<<(N*2))+10],d[(1<<(N*2))+10],n,k,vis[(1<<(N*2))+10],ka; 6 char s[100+10][N+5]; 7 int dp(int S) { 8 if(siz[S]==0)return 0; 9 if(siz[S]==1)return 0; 10 if(siz[S]==2)return 1; 11 int& ret=d[S]; 12 if(vis[S]==ka)return ret; 13 vis[S]=ka; 14 ret=inf; 15 for(int i=0; i<n; ++i)if((S>>(2*i)&3)==0)ret=min(ret,max(dp(S|(1<<(2*i))),dp(S|(2<<(2*i))))); 16 return ++ret; 17 } 18 19 void dfs(char* s,int u,int S) { 20 if(u==n) {siz[S]++; return;} 21 dfs(s,u+1,S); 22 if(s[u]==‘0‘)dfs(s,u+1,S|(1<<(u*2))); 23 else if(s[u]==‘1‘)dfs(s,u+1,S|(2<<(u*2))); 24 } 25 26 int main() { 27 memset(vis,0,sizeof vis); 28 while(scanf("%d%d",&n,&k)&&n) { 29 ++ka; 30 memset(siz,0,sizeof siz); 31 for(int i=0; i<k; ++i)scanf("%s",s[i]); 32 for(int i=0; i<k; ++i)dfs(s[i],0,0); 33 printf("%d ",dp(0)); 34 } 35 return 0; 36 }
以上是关于UVA - 1252 Twenty Questions (状压dp+vis数组加速)的主要内容,如果未能解决你的问题,请参考以下文章
(状压dp)UVA - 1252 Twenty Questions
UVA - 1252 Twenty Questions (状压dp+vis数组加速)