Uva1252 Twenty Questions

Twenty Questions

https://odzkskevi.qnssl.com/15b7eb4cd1f75f63cee3945b0b845e4f?v=1508411736

【题解】

dp[S1][S2]表示已经询问了S1,确定有S2,还需要至少多少次询问

dp[S1][S2] = max(min(dp[S1 | k][S2 | k], dp[S1 | k, S2 | j)) + 1

即枚举询问哪一个k,得到答复是有/没有中取还需要的询问次数最大的,然后

在所有的k中找最小的,表示到了S1,S2这个状态我要去询问k

预处理cnt[S1][S2]表示S2是S1的子集且属性为S2的物体的个数

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <sstream>
 7 #include <vector>
 8 #include <string>
 9 #include <cmath> 
10 #include <queue>
11 #define min(a, b) ((a) < (b) ? (a) : (b))
12 #define max(a, b) ((a) > (b) ? (a) : (b))
13 
14 inline void swap(int &a, int &b)
15 {
16     int tmp = a;a = b;b = tmp;
17 }
18 
19 inline void read(int &x)
20 {
21     x = 0;char ch = getchar(), c = ch;
22     while(ch < '0' || ch > '9')c = ch, ch = getchar();
23     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
24     if(c == '-')x = -x;
25 }
26 
27 const int INF = 0x3f3f3f3f;
28 const int MAXN = 128 + 5;
29 const int MAXM = 11 + 2;
30 
31 int ma,dp[1 << MAXM][1 << MAXM], cnt[1 << MAXM][1 << MAXM], n, m, num[MAXN];
32 char s[MAXM];
33 /*
34 dp[s1][s2]表示已经询问了s1,确定有s2,还需要询问多少次 
35 */
36 int DP(int s1, int s2)
37 {
38     if(cnt[s1][s2] <= 1)return 0;
39     if(dp[s1][s2] > -1)return dp[s1][s2];
40     dp[s1][s2] = INF;
41     for(register int i = 0;i < m;++ i)
42     {
43         if(s1 & (1 << i))continue;
44         dp[s1][s2] = min(dp[s1][s2], max(DP(s1 | (1 << i), s2), DP(s1 | (1 << i), s2 | (1 << i))) + 1);
45     }
46     return dp[s1][s2];
47 }
48 
49 int main()
50 {
51     while(scanf("%d %d", &m, &n) != EOF && m + n)
52     {
53         memset(num, 0, sizeof(num));
54         memset(dp, -1, sizeof(dp));
55         memset(cnt, 0, sizeof(cnt));
56         for(register int i = 1;i <= n;++ i)
57         {
58             scanf("%s", s);
59             for(register int j = 0;j < m;++ j)
60                 if(s[j] == '1') num[i] |= (1 << j);
61         }
62         ma = 1 << m;
63         for(register int s1 = 0;s1 < ma - 1;++ s1)
64             for(register int i = 1;i <= n;++ i)
65                 ++ cnt[s1][s1 & num[i]];
66         printf("%d
", DP(0,0));
67     }
68     return 0;
69 }
UVA1252
原文地址:https://www.cnblogs.com/huibixiaoxing/p/7717849.html