zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    微软企业库4.1学习笔记(二十六)Unity依赖注入模块3
    微软企业库4.1学习笔记(三十七)日志模块 在应用中使用日志模块
    微软企业库5.0学习笔记(三十五)数据访问模块 DataSet以及数据库事务
    微软企业库4.1学习笔记(四十一)依赖注入模块Unity 简介
    项目统一开发管理解决方案思路[项目组成员同时做很多项目的解决思路探讨]
    在moss2007WEB应用服务器上发布独立web程序时遇到的问题的解决思路
    工作流表单自定义的误区
    文档库创建的子文件夹的URL显示为 http://[机器名]/.... 导致无法正常访问的问题解决办法
    申请加入 .NET企业应用开发 博客团队请回复
    儿子照片
  • 原文地址:https://www.cnblogs.com/GBRgbr/p/2644270.html
Copyright © 2011-2022 走看看