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 }