UVaLive 4643 / LA 4643 Twenty Questions(对题意的解释已修改)

题目链接:http://livearchive.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2644

PDF:http://livearchive.onlinejudge.org/external/46/4643.pdf

之前翻译有误,已修改!

题目翻译:

Consider a closed world and a set of features that are defined for all the objects in the world. Each feature can be answered with ``yes" or ``no". Using those features, we can identify any object from the rest of the objects in the world. In other words, each object can be represented as a fixed-length sequence of booleans. Any object is different from other objects by at least one feature.

有一个封闭的世界,还有一些问题,这些问题用来区分这个世界中不同的对象。每个问题都用 Yes 或 No 回答,通过利用这些问题,我们可以找出这个世界中任何一个对象。换言之,每个对象都可以用一个布尔串来表示。每个对象都是独一无二的,通过询问至少一个问题,我们可以区别这些对象。

You would like to identify an object from others. For this purpose, you can ask a series of questions to someone who knows what the object is. Every question you can ask is about one of the features. He/she immediately answers each question with ``yes" or ``no" correctly. You can choose the next question after you
get the answer to the previous question.

你想要把每一个对象都区分开。为了实现这个目的,你可以对人询问一些问题。每当你询问一个问题,这个人就会给予你正确的答案 Yes 或 No。当你得到上一题的答案后,你才能选择下一个问题

*.不是选择最少的问题区分开所有人,而是用最少的提问次数区分开所有人

You kindly pay the answerer 100 yen as a tip for each question. Because you don't have surplus money, it is necessary to minimize the number of questions in the worst case. You don't know what is the correct answer, but fortunately know all the objects in the world. Therefore, you can plan an optimal strategy before you start questioning.

你需要给回答者100日元作为每个问题的答谢。但是因为你没有过多的钱,所以你必须尽可能少的选择问题所以你必须用尽可能少的提问次数区分所有人。你不知道什么是正确答案,但幸运的是你了解这个世界里的所有对象。因此,你可以计划出一个最优的提问方案。

The problem you have to solve is: given a set of boolean-encoded objects, minimize the maximum number of questions by which every object in the set is identifiable.

你需要解决的问题就是:给你这些对象的布尔串编码,问你最少要提问几个问题最少需要提问几次,才能把所有的人都区分开来。

Input
The input is a sequence of multiple datasets. Each dataset begins with a line which consists of two integers, m and n: the number of features, and the number of objects, respectively. You can assume 0 < m < 11 and 0 < n 128. It is followed by n lines, each of which corresponds to an object. Each line includes a binary string of
length m which represent the value (``yes" or ``no") of features. There are no two identical objects. The end of the input is indicated by a line containing two zeros. There are at most 100 datasets.

输入

输入有多组数据。每组数据由两个整数开始,m 和 n: m 是问题的个数,n 是对象的数目。0 < m < 11, 0 < n < 128。后面有n行,每行对应一个对象。每行包含一个长度为 m 的二进制串代表每个对象对每个问题的回答。没有任何两个对象是相同的。输入以两个0结束,最多100组数据

Output
For each dataset, minimize the maximum number of questions by which every object is identifiable and output the result.

输出
对每组数据,输出最少提问问题的个数次数

SAMPLE INPUT

8 1 
11010101 
11 4 
00111001100 
01001101011 
01010000011 
01100110001 
11 16 
01000101111 
01011000000 
01011111001 
01101101001 
01110010111 
01110100111 
10000001010 
10010001000 
10010110100 
10100010100 
10101010110 
10110100010 
11001010011 
11011001001 
11111000111 
11111011101 
11 12 
10000000000 
01000000000 
00100000000 
00010000000 
00001000000 
00000100000 
00000010000 
00000001000 
00000000100 
00000000010 
00000000001 
00000000000 
9 32 
001000000 
000100000 
000010000 
000001000 
000000100 
000000010 
000000001 
000000000 
011000000 
010100000 
010010000 
010001000 
010000100 
010000010 
010000001 
010000000 
101000000 
100100000 
100010000 
100001000 
100000100 
100000010 
100000001 
100000000 
111000000 
110100000 
110010000 
110001000 
110000100 
110000010 
110000001 
110000000 
0 0

SAMPLE OUTPUT
0 
2 
4 
11 
9

 

简而言之这题的意思就是最少选多少问题最少提问多少次能把所有人区分开。

感谢 @蚀 的解释:

举个简单例子:
3 4
001
011
100
000

你WA的程序答案是3,正确答案是2。
先问第三个问题,如果是Yes再问第二个问题,否则问第一个问题,所以只问了两次。

我之前的理解的题意是选最少的问题,用的是枚举做法,这样是不对的:

我最先想到的方法是枚举,因为最多只有11个问题,128个人,数量都不是很大,用二进制表示每个问题选还是不选,然后判断有没有人的回答是重复的。

动规AC代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 
 5 const int MAXN = 150;
 6 const int MAXSIZE = ( 1 << 11 ) + 10;
 7 
 8 int question[MAXN];   //每个人对每个问题的回答,二进制表示
 9 char str[20];
10 int dp[MAXSIZE][MAXSIZE];  //状态压缩
11 int Q, n;
12 
13 int min( int a, int b )
14 {
15     return a < b ? a : b;
16 }
17 
18 int max( int a, int b )
19 {
20     return a > b ? a : b;
21 }
22 
23 //记忆化搜索
24 int DP( int state, int quest )    //state表示选择了哪几个问题,quest表示对每个问题的答案
25 {
26     if ( dp[state][quest] != -1 ) return dp[state][quest];
27 
28     int cnt = 0;
29     for ( int i = 0; i < n; i++ )
30         if ( ( question[i] & state ) == quest )
31             ++cnt;
32 
33     if ( cnt <= 1 ) return dp[state][quest] = 0;  //如果没有两个人答案是重复的
34 
35     int ans = (1 << 30);
36     for ( int i = 0; i < Q; i++ )
37     {
38         if ( state & ( 1 << i ) ) continue;    //如果问题 i 已经在状态state中, 跳过
39         dp[state|(1 << i)][quest] = DP( state|(1 << i), quest ); //选择问题i, 对问题i的回答为"否"
40         dp[state|(1 << i)][quest|(1 << i)] = DP( state|(1 << i), quest|(1 << i) ); //选择问题i, 对问题i的回答为"是"
41         ans = min( ans, max( dp[state|(1 << i)][quest], dp[state|(1 << i)][quest|(1 << i)] ) + 1 );
42     }
43     return dp[state][quest] = ans;
44 }
45 
46 int main()
47 {
48     while ( scanf("%d%d", &Q, &n), Q || n )
49     {
50         memset( question, 0, sizeof(question) );
51         for ( int i = 0; i < n; i++ )
52         {
53             scanf("%s", str);
54             for ( int j = 0; j < Q; j++ )
55             {
56                 if ( str[j] == '1' )
57                    question[i] += (1 << j);   //用二进制表示对问题的回答
58             }
59         }
60 
61         memset( dp, -1, sizeof(dp) );
62         printf( "%d\n", DP(0, 0) );
63     }
64     return 0;
65 }
posted @ 2012-08-17 16:35  冰鸮  阅读(499)  评论(2编辑  收藏  举报