码迷,mamicode.com
首页 > 编程语言 > 详细

UVA - 1252 Twenty Questions (状压dp+vis数组加速)

时间:2019-02-15 01:09:34      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:情况   ++   uva   mes   div   最优   c++   时间   else   

有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\n",dp(0));
34     }
35     return 0;
36 }

 

UVA - 1252 Twenty Questions (状压dp+vis数组加速)

标签:情况   ++   uva   mes   div   最优   c++   时间   else   

原文地址:https://www.cnblogs.com/asdfsag/p/10381301.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!