免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4458 | 回复: 2
打印 上一主题 下一主题

[C++] C++写的一个简单的两个逻辑推理题求解算法 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-08-31 17:35 |只看该作者 |倒序浏览
有C++和python两个版本的,前一个是C++的
http://bbs.chinaunix.net/thread-976470-1-1.html

论坛徽章:
0
2 [报告]
发表于 2007-09-03 03:52 |只看该作者
这两道题目我不会做帮我看看 python的代码我弄不出来清华附中有四位同学中的一位做了好事,不留名,表扬信来了之后,校长问这四位是谁做的好事。
A说:不是我。
B说:是C。
C说:是D。
D说:他胡说。
        已知三个人说的是真话,一个人说的是假话。现在要根据这些信息,找出做了好事的人。



  1. #include <stdio.h>

  2. #define TOTAL_NUM 4
  3. #define CORRECT_NUM 3

  4. enum std_id { STD_A=0, STD_B, STD_C, STD_D };
  5. enum std_statu { DONOT=0, DO };

  6. static int test( int std, int statu, int condition )
  7. {
  8.         if( (statu && std==condition) || (!statu && std!=condition) )
  9.                 return 1;
  10.         else
  11.                 return 0;
  12. };


  13. int main( void )
  14. {
  15.         int guess, correct_time;

  16.         for( guess=0; guess<TOTAL_NUM; guess++ )
  17.         {
  18.                 correct_time = test( STD_A, DONOT, guess );
  19.                 correct_time += test( STD_C, DO, guess );
  20.                 correct_time += test( STD_D, DO, guess );
  21.                 correct_time += test( STD_D, DONOT, guess );
  22.                 if( CORRECT_NUM==correct_time )
  23.                 {
  24.                         printf( "the student is %c\n", ('A'+guess) );
  25.                 }
  26.         };

  27.         return 0;
  28. }
复制代码



这个可以吗?

static int test( int std, int statu, int condition );
函数 test用来测试,描述的学生和他的状态(做了还是没做)是否与假设的条件成立;如果成立返回1,不然返回0!


主函数用for( guess=0; guess<TOTAL_NUM; guess++ )来依次做假设
然后为每次假设进行4个人说话的判断
test( STD_A, DONOT, guess );  //A说:不是我。
test( STD_C, DO, guess );     //B说:是C。
test( STD_D, DO, guess );     //C说:是D。
test( STD_D, DONOT, guess );   //D说:他胡说。


然后判断当前假设是否是3个真话(即一个假话),是的话则打印出假设
if( CORRECT_NUM==correct_time )
{
        printf( "the student is %c\n", ('A'+guess) );
}

程序就结束了

编译运行
dorainm@lfs ~/workroom/c/conseq $ gcc -o conseq conseq.c
dorainm@lfs ~/workroom/c/conseq $ ./conseq
the student is C
dorainm@lfs ~/workroom/c/conseq $

[ 本帖最后由 dorainm 于 2007-9-3 05:36 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2007-09-03 05:27 |只看该作者
原帖由 rubee 于 2007-8-14 22:10 发表
第二题:某地刑侦大队对涉及六个嫌疑人的一桩疑案进行分析:
A、B 至少有一人作案;
A、E、F 三人中至少有两人参与作案;
A、D 不可能是同案犯;
B、C 或同时作案,或与本案无关;
C、D 中有且仅有一人作案;
如果 D 没有参与作案,则 E 也不可能参与作案。
试编一程序,将作案人找出来



比较笨,用的是穷举!!

跟上题一样,排列出所有可能的罪犯组合类型,
我们用一个int来表达,最低位为A,依次升高为B、C、D、E、F
(既A是第0位、B第1位、C2、D3、E4、F5)
如果A、B、D是罪犯的话,那表达出来就是
(1<<0)+(1<<1)+(1<<3) = 1+2+8 = 13

现在列举所有的罪犯组合,只需要循环,从0到(2^6-1)

思想是这个样子的,把所有一切都转化成数目的思考!
比如X、Y同犯,则表明数目是2
要判断罪犯列表中X、Y是否是同犯,
只要把X、Y的组合与整体的罪犯组合与运算后,
2进制中依然能数出来2个1,则确定X、Y是同犯成立

statu2int函数就是属状态码的2进制中数有多少个罪犯数目的
static int statu2int( int statu )

check则用要判断的罪犯列表、他们的关系数量,与输入的假设犯罪组合进行比较,如果成立返回1,否则返回0
static int check( int men, int num, int condition )


main中,循环所有组合,依次判断题目中的条件,
如果不符合,就continue;如果都符合,则打印出当前罪犯组合

下面看具体代码


  1. #include <stdio.h>
  2. #include <math.h>

  3. #define NUM 6

  4. int statu = 0;
  5. enum man { A=0, B, C, D, E, F };


  6. static int statu2int( int statu )
  7. {
  8.         int i, retval = 0;

  9.         for( i=0; i<NUM; i++ )
  10.                 if( (statu>>i)&0x01 ) retval++;

  11.         return (retval);
  12. };


  13. static int check( int men, int num, int condition )
  14. {
  15.         if( num==statu2int(men&condition) )
  16.                 return 1;
  17.         else
  18.                 return 0;
  19. };


  20. int main( void )
  21. {
  22.         int guess, i;

  23.         for( guess=0; guess<pow(2,NUM); guess++ )
  24.         {
  25.                 /*A和B至少有1个人作案*/
  26.                 if( !( check( (1<<A)+(1<<B), 1, guess ) || check( (1<<A)+(1<<B), 2, guess ) ) )    continue;

  27.                 /*A、E、F至少有2个人作案*/
  28.                 if( !( check( (1<<A)+(1<<E)+(1<<F), 2, guess ) || check( (1<<A)+(1<<E)+(1<<F), 3, guess ) ) ) continue;

  29.                 /*A、D不可能是同犯*/
  30.                 if( check( (1<<A)+(1<<D), 2, guess ) )  continue;

  31.                 /*B、C或同时作案,或与本案无关*/
  32.                 if( !( check( (1<<B)+(1<<C), 0, guess ) || check( (1<<B)+(1<<C), 2, guess ) ) )    continue;

  33.                 /*C、D 中有且仅有一人作案*/
  34.                 if( !check( (1<<C)+(1<<D), 1, guess ) )        continue;

  35.                 /*如果 D 没有参与作案,则 E 也不可能参与作案*/
  36.                 if( check( (1<<D), 0, guess ) )
  37.                         if( !check( (1<<E), 0, guess ) )       continue;

  38.                 for( i=0; i<NUM; i++ )
  39.                 {
  40.                         if( (guess>>i)&0x01 ) fputc( 'A'+i, stdout );
  41.                 }
  42.                 printf( "\n" );
  43.         }

  44.         return 0;
  45. }
复制代码


编译运行
dorainm@lfs ~/workroom/c/conseq $ gcc -o conseq2 conseq2.c
dorainm@lfs ~/workroom/c/conseq $ ./conseq2
ABCF
dorainm@lfs ~/workroom/c/conseq $


犯罪列表出来了:)

[ 本帖最后由 dorainm 于 2007-9-3 05:28 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP