【文档说明】逻辑思维与计算机解题1课件12.ppt,共(56)页,307.164 KB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-77586.html
以下为本文档部分文字说明:
1逻辑思维与计算机解题2将实际问题抽象为逻辑关系枚举法解题思路关系与关系表达式程序的循环结构与分支结构学习目标31.关系运算符与关系表达式2.人的思维到用计算机语言的表示3.枚举的概念与思路4.循环结构5.分支结构内容要点4计算机强大的逻辑分析功能是由人通过程序赋给它的。一些逻辑问题必须转换成
计算机能够看得懂的数学表达式和一定的程序指令。这一章我们通过例子来介绍如何将人对问题的思考转换为让计算机能解的数学表达式,同时给出一些通常要用到的程序结构和C/C++语句。5清华附中有四位同学中的一位做了好事,不留名,表扬信来了之后,校长问这四位是谁做的好事。A说:不是我。B说:是C。
C说:是D。D说:他胡说。已知三个人说的是真话,一个人说的是假话。现在要根据这些信息,找出做了好事的人。【例1】“谁做的好事”6为了解这道题,我们需要学习如何通过逻辑思维与判断解这类问题的思路。7将四个人说的四句话写成关系表达式。在声明变量
时,我们让thisman表示要寻找的做了好事的人,定义它是字符变量。charthisman=„‟;//定义字符变量并将其初始化为空让“==”的含义为“是”,让“!=”的含义为“不是”。8利用关系表达式将四个人所说的话表示成说话人说的话写成
关系表达式A“不是我”thisman!=„A‟B“是C”thisman==„C‟C“是D”thisman==„D‟D“他胡说”thisman!=„D‟9A、B、C、D四个人,只有一位是做好事者。令做好事者为1,未做好事者为0,可以有如下4中状态(情况)枚举法的思路状态ABCD1100
020100300104000110这四种状态可简化写成状态赋值表达式1thisman=„A‟2thisman=„B‟3thisman=„C‟4thisman=„D‟显然第一种状态是假定A是做好事者,第二种状态是假定B是做好事者,…。所谓枚举
是按照这四种假定逐一地去测试四个人的话有几句是真话,如果不满足三句为真,就否定掉这一假定,换下一个状态再试。具体做法如下:11(1)假定让thisman=„A‟代入四句话中状态说的话关系表达式CAthisman!=„A‟;„A‟!=„A‟0Bthisman==„C‟;„A‟==„C‟0C
thisman==„D‟;„A‟==„D‟0Dthisman!=„D‟;„A‟!=„D‟1四个关系表达式的值的和为1,显然不是„A‟做的好事12(2)假定让thisman=„B‟代入四句话中状态说的话关系表
达式CAthisman!=„A‟;„B‟!=„A‟1Bthisman==„C‟;„B‟==„C‟0Cthisman==„D‟;„B‟==„D‟0Dthisman!=„D‟;„B‟!=„D‟1四个关系表达式的值的和为2,显然不是„B‟做的好事13(3)假定让thisman=
„C‟代入四句话中状态说的话关系表达式CAthisman!=„A‟;„C‟!=„A‟1Bthisman==„C‟;„C‟==„C‟1Cthisman==„D‟;„C‟==„D‟0Dthisman!=„D‟;„C‟!=„D‟1四个关系
表达式的值的和为3,就是„C‟做的好事14综上所述一个人一个人去试,就是枚举。从编写程序看,实现枚举最好用循环结构。这部分的程序写出如下:for(k=1;k<=4;k=k+1)//计数型循环,循环的控制变量为k{thisman=64+k;//产生被试者,依次为
‟A‟,‟B‟,‟C‟,‟D‟sum=(thisman!=‟A‟)//测试‟A‟的话是否为真+(thisman==‟C‟)//测试‟B‟的话是否为真+(thisman==‟D‟)//测试‟C‟的话是否为真+(thisman!=„D‟);//测试‟D‟的话是否为真…}15NS图有了上述了
解之后,我们来看解“谁做的好事”的程序框图for(k=1;k<=4;k=k+1)假真g!=1sum==3被试者thisman=64+k;sum=(被试者thisman!=„A‟)+(被试者thisman==„C‟)+(被试者thisman==„D‟)+(被试者thisman!=„D‟);
假真输出该被试者;有解标志g=1;输出无解信息;图4.716#include<iostream>//预编译命令usingnamespacestd;intmain()//主函数{//主函数开始intk=0,sum=0,g=0;//定义整型变量,均初始化为0charthisman
='';//定义字符变量,初始化为空for(k=1;k<=4;k=k+1)//k是循环控制变量{//for循环体开始thisman=64+k;sum=(thisman!='A')+(thisman=='C')+(thisman==
'D')+(thisman!='D');if(sum==3){//如果3句话为真,则输出该人cout<<"做好事者为"<<char(64+k)<<endl;g=1;//有解标志置1}}//for循环体结束if(g!=1){cout<<"Can‟tf
ound!"<<endl;}//输出无解信息return0;}//主函数结束17#include<iostream>//预编译命令usingnamespacestd;voidmain(){intk=0,sum=
0,g=0;charthisman='';for(k=1;k<=4;k=k+1){thisman=64+k;sum=(thisman!='A')+(thisman=='D')+(thisman=='C')+(thisman!='D');if(sum==3){c
out<<"做好事者为"<<char(64+k)<<endl;g=1;}}if(g!=1){cout<<"Can‟tfound!"<<endl;}}18换个思路数字1表示A数字2表示B数字3表示C数字4表示D让K表
示要找的人,K从1到4,表示从A找到D,这时A说:不是我;可形式化为K!=1;B说:是C;可形式化为K==3;C说:是D;可形式化为K==4;D说:他胡说;可形式化为K!=4;19#include<iostream>//预编译命令usingnamespacestd
;voidmain()//主函数{//主函数开始intk=0,sum=0,g=0;//声明变量为整数类型,且均初始化为0for(k=1;k<=4;k=k+1)//循环从k为1到4,{sum=0;//循环体
内的初始化,用sum累计真话数if(k!=1)sum=sum+1;//如A的话为真,则让sum加1;if(k==3)sum=sum+1;//如B的话为真,则让sum加1;if(k==4)sum=sum+1;//如C的话为真,则让sum加1;if(k!=4)sum=sum+1;//如D
的话为真,则让sum加1;if(sum==3)//若有三句话为真,则做下列两件事{cout<<"Thismanis"<<char(64+k)<<endl;//输出做好事者g=1;//让有解标志置1}}if(g!=1)//
则输出无解信息{cout<<"Can‟tfound!"<<endl;}}20for(k=1;k<=4;k=k+1){sum=0;if(k!=1)sum=sum+1;//如A的话为真,则让sum加1;if(k==3)sum=sum+1;//如B的话为真,
则让sum加1;if(k==4)sum=sum+1;//如C的话为真,则让sum加1;if(k!=4)sum=sum+1;//如D的话为真,则让sum加1;...}21#include<iostream.h>//预编译命令intmain()//
主函数{//主函数开始intk=0,g=0;//声明变量为整数类型,且均初始化为0for(k=1;k<=4;k=k+1)//k既是循环控制变量,也表示第k个人{if(((k!=1)+(k==3)+(k==4)+(k!=4))=
=3){//如果4句话有3句话为真,则输出该人cout<<"做好事者为"<<char(64+k)<<endl;g=1;//有解标志置1}}if(g!=1)//g!=1则输出无解信息{cout<<"Can‟tfound!"<<endl;}return0;}//主函数结
束上述程序可以简化为:22for(k=1;k<=4;k=k+1){if(((k!=1)+(k==3)+(k==4)+(k!=4))==3){cout<<"做好事者为"<<char(64+k)<<endl;g=
1;}}A说B说C说D说23for(k=1;k<=4;k=k+1){if(((k!=1)+(k==3)+//如果4句话有3句真话,就(k==4)+//输出做好事者(k!=4))==3){cout<<“做好事
者为”<<char(64+k)<<endl;g=1;}}24思考和讨论for(intk=68;k>=65;k=k-1){if(((k!=65)+(k==67)+//如果4句话有3句真话,(k==68)+//就输出做好事者(k!=68))==3){cout<<“做好事
者为”<<char(k)<<endl;g=1;}}25某地刑侦大队对涉及六个嫌疑人的一桩疑案进行分析:A、B至少有一人作案;A、E、F三人中至少有两人参与作案;A、D不可能是同案犯;B、C或同时作案,或
与本案无关;C、D中有且仅有一人作案;如果D没有参与作案,则E也不可能参与作案。试编一程序,将作案人找出来。例226思路:1、案情分析:将案情的每一条写成逻辑表达式,第一条用CC1表示,第二条用CC2表示,
……27CC1:A和B至少有一人作案令A变量表示A作案,B变量表示B作案显然这是或的关系,有CC1=(A||B)28CC2:A和D不可能是同案犯可以分析为:A和D是同案犯,写成A&&DA和D不是同案犯,写成!(A&&D)因此有CC2=!
(A&&D)29CC3:A、E、F中至少有两人涉嫌作案分析有三种可能第一种,A和E作案,(A&&E)第二种,A和F作案,(A&&F)第三种,E和F作案,(E&&F)这三种可能性是或的关系,因此有CC3=(A&&E)||(A&&F)||(E&&F)30CC
4:B和C或同时作案,或都与本案无关第一种情况:同时作案(B&&C)第二种情况:都与本案无关(!B&&!C)两者为或的关系,因此有CC4=(B&&C)||(!B&&!C)31CC5:C、D中有且仅有
一人作案CC5=(C&&!D)||(D&&!C)32CC6:如果D没有参与作案,则E也不可能参与作案。分析这一条比较麻烦一些,可以列出真值表再归纳DE!ECC6含义1101D作案,E也作案可能1011
D作案,E不作案可能0011D不作案,E也不可能作案可能0100D不作案,E却作案不可能33()()()()DEDEDEDEDEDEDEDEEEDDDECC6=D||!E1011以上是案情分析,已经化
成了计算机可解的逻辑表达式DDEE346个人每个人都有作案或不作案两种可能,因此有种组合,从这些组合中挑出符合6条分析的作案者。定义6个整数变量,分别表示6个人A,B,C,D,E,F。枚举每个人的可能性让0表
示不是罪犯;让1表示就是罪犯。622、采取枚举方法,枚举什么呢?枚举组合35为了讲多重循环先做些铺垫编一个程序输出000000000001000010......111111从高位到低位,分别用ABCDEF
来表示36ABCDEF000000000001000010………………11111137写一个从000000到111111的程序for(A=0;A<=1;A=A+1)for(B=0;B<=1;B=B+1)for(C=0;C<=1;C=C+1)for(D=0;D<
=1;D=D+1)for(E=0;E<=1;E=E+1)for(F=0;F<=1;F=F+1){cout<<A<<B<<C<<D<<E<<F<<endl;}38作业请你完成输出000000到111111的程序并上机运行下面是据案情分析采用枚举法寻找罪犯的程序框图39输出CC1+CC2+CC3
+CC4+CC5+CC6==6假真CC1=A||B;CC2=!(A&&D);CC3=(A&&E)||(A&&F)||(E&&F);CC4=(B&&C)||(!B&&!C);CC5=(C&&!D)||(D&&!C);CC6=D||(!E);
for(F=0;F<=1;F=F+1)for(E=0;E<=1;E=E+1)for(D=0;D<=1;D=D+1)for(C=0;C<=1;C=C+1)for(B=0;B<=1;B=B+1)for(A=0;A<=1;A=A+1)40为了给出每个人是否为罪犯的信息,程序中定义了一个二维数组。ch
arinfo[2][9]={“不是罪犯”,“是罪犯”};有两个字串每串最多有9-1个英文字符是罪犯\0不是罪犯\0012345678info为数组名1041char是说,info数组的元素为字符,[2]为下标,表示有两个字符串,每个字符串最多有9-1个字符。
因为英文字符占一个字节,而汉字占两个字节,故4个汉字要占8个英文字符的地方。每一字串后面自动跟一个空字符‘\0‟因此可以看出:第0号字符串info[0]的内容为“不是罪犯”。第1号字符串info[1]的内容为“是罪犯”。42在输出时用cout<<“A:”<<in
fo[A]<<endl;如果A为0,则输出A:不是罪犯如果A为1,则输出A:是罪犯43#include<iostream>usingnamespacestd;intmain(void)//案情分析{//A和B至少有一人作案;cc1=
A||B//A和D不可能是同案犯;cc2=!(A&&D)//A,E,F中至少有两人涉嫌作案cc3=(A&&E)||//(A&&F)||//(E&&F)//B和C或同时作案或都与本案无关cc4=(B&&C)||(!B&&!C)//C,D中有且仅有一人作案;cc5
=(C&&!D)||(D&&!C)//如果D没有参与作案,则E也不可能参与作案;cc6=D||(!E)//编程找出犯罪嫌疑人.intcc1,cc2,cc3,cc4,cc5,cc6;//定义6个变量,分别表示6句话intA,B,C,D,E,F;//定义6个变量,分别表示6个人char
info[2][9]={"不是罪犯","是罪犯"};//定义二维数组,给出是否罪犯信息44for(A=0;A<=1;A=A+1)//枚举Afor(B=0;B<=1;B=B+1)//枚举Bfor(C=0;C<=1;C
=C+1)//枚举Cfor(D=0;D<=1;D=D+1)//枚举Dfor(E=0;E<=1;E=E+1)//枚举Efor(F=0;F<=1;F=F+1)//枚举F{cc1=A||B;cc2=!(A&&D);cc3=(A&&E)|(A&&F)||(E&&F)
;cc4=(B&&C)||(!B&&!C);cc5=(C&&!D)||(D&&!C);cc6=D||(!E);45//测试6句话都为真时,才输出谁是罪犯if(cc1+cc2+cc3+cc4+cc5+cc6==6){//输出判断结果
cout<<"A:"<<info[A]<<endl;cout<<"B:"<<info[B]<<endl;cout<<"C:"<<info[C]<<endl;cout<<"D:"<<info[D]<<endl;cout<<"E:"<<info
[E]<<endl;cout<<"F:"<<info[F]<<endl;}//输出结束}//循环结束return0;}//主函数体结束46讨论47大家参与讨论的题五位跳水高手将参加十米高台跳水决赛,有好事者让五个人据实力预测比赛结果。A选手说:B第二,
我第三;B选手说:我第二,E第四;C选手说:我第一,D第二;D选手说:C最后,我第三;E选手说:我第四,A第一;决赛成绩公布之后,每位选手的预测都只说对了一半,即一对一错,请编程解出比赛的实际名次。48思路:1、首先是将五个人的预测写成逻辑表达式:让关系运算符“==”的含义
是“是”。让数字1、2、3、4、5分别表示名次第一、第二,…,第五。让整型变量A、B、C、D、E分别表示每个选手所得名次。A选手说:B==2,A==3;B选手说:B==2,E==4;C选手说:C==1,D==2;
D选手说:C==5,D==3;E选手说:E==4,A==1;492、考虑到每个人说的话是一对一错,即一真一假,比如A说的(B==2)+(A==3)应该是11+0=10+1=150我们可以归纳出要同时满
足五个人所说的话都符合一半对一半错的条件是ta=((B==2)+(A==3))==1;符合A选手的话tb=((B==2)+(E==4))==1;符合B选手的话tc=((C==1)+(D==2))==1;符合C选手的话td=((C==
5)+(D==3))==1;符合D选手的话te=((E==4)+(A==1))==1;符合E选手的话因为ta,tb,…,te非1即0,五个条件值都加在一起05tatbtctdte51ta的取值是0或1ta的取值取决于下列关系((B==2)+(A==3))
==1B==2---------可能是0或1A==3---------可能是0或1((B==2)+(A==3))---可能是0或1或2只有上式为1才能使ta为1523、只有等于5时才都符合每个人所说的话,这仅只是符合题意的一个必要条件,同时还得考虑
A、B、C、D、E的取值不得有相同者,,,,{1,2,3,4,5}ABCDEABCDE且可以考虑****120ABCDE是一个条件534、仍然可以用枚举的方法,让变量A、B、C、D、E在1~5中取值,形成满足上述
条件的A~E的组合,即是所求。这时可用循环结构,如下所示54输出A,B,C,D,Et==5假真ta=((B==2)+(A==3))==1;tb=((B==2)+(E==4))==1;tc=((C==1)+(D==2))==1;
td=((C==5)+(D==3))==1;te=((E==4)+(A==1))==1;t=ta+tb+tc+td+te;假真A*B*C*D*E==120E=15-(A+B+C+D);for(D=1;D<=5;D=D+1)for(C=1;C<=5;C=
C+1)for(B=1;B<=5;B=B+1)for(A=1;A<=5;A=A+1)55作业:1请你自己完成这个程序;2思考如何提高效率?3思考还有什么其它解法?56结束