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 }

你可能感兴趣的:(live)