用穷举法设计算法
用穷举法设计算法
问题1: 有一把锁和一串钥匙(共有10把钥匙), 怎样找出所有开这把锁的钥匙?
用穷举法设计算法
穷举算法的概念: 穷举算法就是按问题本身的性质,通过多 重循环一一列举出该问题所有可能的解(不能 遗漏,也不能重复),并在逐一列举的过程中, 检验每个可能的解是否是问题的真正解,若是, 我们采用这个解,否则抛弃它。
第2次优化
只要求出x,y后,z可以由方程(4)直接计算出来。在方程 (3)中,假设y=0,则x=14,假设x=0,则y=25。即x,y的枚 举范围是 0≤x≤14,0≤y≤25. for(x=0;x<=14;x++) for(y=0;y<=25;y++) if(7*x+4*y==100) { z=100-x-y; output(x,y,z); }
标准输入输出速度比较快。
流输入输出在数据比较多,比如 1000000个数据的时候会很慢。
ios::sync_with_stdio(false)
采用穷举算法解题的基本思想: (1) 明确问题要求,确定枚举对象,用合适类型 的变量表示枚举对象。 (2) 明确枚举对象的取值范围。 (3) 根据题目要求,写出有关的条件表达式。这 里条件表达式可以是数学表达式、关系表达式或 逻辑表达式; (4) 使用循环语句枚举出可能的解,在循环体内 验证各种条表达式是否满足; (5) 根据问题背景,优化程序,以便缩小搜索范 围,减少程序运行时间。
⑵关系表达式的计算结果只有0(假)和1(真)两种结果。 现在“已知三个人说的是真话,一个人说假话”,也就是表 中的4个关系表达式中有3个是真的,1个是假的。 因此4个关系表达式的值的和应该等于3。定义变量cond 表示四个关系表达式的和 cond= thisman!=‘A’+ thisman==‘C’+ thisman==‘D’+ thisman!=‘D’ 那么,cond==3
#include<cstdio> using namespace std; int main() { char thisman; int cond; for(thisman='A'; thisman<='D';thisman++) { cond=(thisman!=‘A’)+(thisman==‘C’) +(thisman==‘D’)+(thisman!=‘D); if(cond==3) printf("做好事的人是:%C\n",thisman); } }
1.算法分析
将相关的陈述写成关系表达式和逻辑表达式
⑴我们把四个人说的四句话写成关系表达式。 定义变量thisman表示做好事的人(将其定 义为字符型)。
四个人说的话 A说:不是我。 关系表达式 thisman!=‘A’
B说:是C。
C说:是D。 D说:他胡说。
thisman==‘C’
thisman==‘D’ thisman!=‘D’
1.分析与算法设计 (1)定义变量: a—洞庭湖,a可能的取值{1,2,3,4} b—洪泽湖,b可能的取值{1,2,3,4} c—鄱阳湖,c可能的取值{1,2,3,4} d—太湖, d可能的取值{1,2,3,4} a,b,c,d四个变量的取值互不相同,1表示最大,四 表最小
(2) 用变量表示条件 A学生的叙述可表示为:a==1, b==4,c==3 这是 三个关系表达式,由于每个学生的叙述只有一个 正确,所以这三个关系表达式的值的和应等于1。 A学生的叙述可表示成: ( (a==1)+(b==4)+(c==3))==1 同理,B学生的叙述表示成: ((b==1)+(a==4)+(c==2)+(d==3))==1 C学生的叙述可表示成: ((b==4)+(a==3)) ==1 D学生的叙述可表示成: ((c==1)+(d==4)+(b==2)+(a==3))==1
【例8】(白帽子和红帽子问题)厅内有5个 人,他们均戴着帽子-白帽子和红帽子。 已知戴白帽子的说真话,戴红帽子的说假 话,请从他们各自提供的线索辨别谁戴白 帽子,谁戴红帽子。
⑶穷举试探。我们现在并不知道是谁做得好事,但我们知 道做好事的人是A,B,C,D四个人中的某一个。因此,我们可 以一个一个地试探。
先假设是A做的好事,即thisman=‘A’,然后看cond==3条件是否成立, 然后再假设是B做的好事,即thisman=‘B’,再测试条件cond==3 是否成 立,如此继续下去,将所有可能的情况(本例自有4种情况)都测试一 遍,在实际编程过程中,都是使用循环来一个一个的测试
i←1 i≤10
Y i是3的倍数 N
N
Y
输出i
i← i +1
结束
问题3:从1~100中找出所有能被7或9整除 的数。用流程图描述解决此数学问题的算法。
开始
#include<cstdio> using namespace std; int main() { int i; for(i=1;i<=100;i=i+1) {if (i%7==0||i%9==0) printf(“%d\n”,i); } }
【例7】: (四大湖问题)上地理课时,四个学生回答 我国四个淡水湖大小时说: A学生:洞庭湖最大,洪泽湖最小,鄱阳湖第3 B学生:洪泽湖最大,洞庭湖最小,鄱阳湖第2, 太湖第3 C学生:洪泽湖最小,洞庭湖第3 D学生:鄱阳湖最大,太湖最小,洪泽湖第2,洞 庭第3 对于湖的大小,每个学生仅答对一个,请编程判 断四个湖的大小
#include<cstdio> 修改错误 using namespace std; int main() { int x,y,z; for(x=0;x<=100;x++) for(y=0;y<=100;y++) for(z=0;z<=100;z++) if(x+y+z==100 && 15*x+9*y+z==300) printf("x=%d,y=%d,z=%d\n",x,y,z); } x=0,y=25,z=75 x=4,y=18,z=78 x=8,y=11,z=81 x=12,y=4,z=84
(2)确定枚举变量的取值范围。显然,x,y,z的取值范围 为 0≤x,y,z≤100;
#include<cstdio> using namespace std; int main() { int x,y,z; for(x=0;x<=100;x++) for(y=0;y<=100;y++) for(z=0;z<=100;z++) if(x+y+z==100 && 5*x+3*y+z/3==100) printf("x=%d,y=%d,z=%d\n",x,y,z); } x=0,y=25,z=75 x=3,y=20,z=77 x=4,y=18,z=78 有错误 x=7,y=13,z=80 x=8,y=11,z=81 x=11,y=6,z=83 x=12,y=4,z=84
穷举算法的要点: 列举所有可能的解(不能遗漏,也不能重 复),检验每个可能的解。 Nhomakorabea
问题2:从1~10中找出所有是3倍数的数。 用流程图描述解决此数学问题的算法。
开始
#include<cstdio> using namespace std; int main() {int i=1; while(i<=10) {if (i%3==0) printf(“%d\n”,i); i=i+1; } }
(3) 穷举: 穷举a,b,c,d四个变量的所有可能取值,进行测试, 满足前述四个条件的取值就是我们所要的结果
for(a=1;a<=4;a++) for(b=1;b<=4;b++) for(c=1;c<=4;c++) for(d=1;d<=4;d++) { ca=((a==1)+(b==4)+(c==3))==1; cb=((b==1)+(a==4)+(c==2)+(d==3))==1; cc=((b==4)+(a==3) )==1; cd=((c==1)+(d==4)+(b==2)+(a==3))==1; if(ca && cb && cc && cd) { printf("TongTing=%d\n",a); printf("Hongzhe=%d\n",b); printf("Poyang=%d\n",c); printf("Taihu=%d\n",d); } }//end for
}
x=4,y=18,z=78 x=8,y=11,z=81 x=12,y=4,z=84 Press any key to continue
逻辑推理问题
逻辑推理问题
【例6】:(谁做的好事)已知有有四位同学中的一 位做了好事,不留名,表扬信来了之后,校长问这四 位是谁做的好事。 A说:不是我。 B说:是C。 C说:是D。 D说:他胡说。 已知三个人说的是真话,一个人说的是假话。现在 要根据这些信息,找出做了好事的人。
【例5】:(百钱买百鸡问题)大约在公元5世纪,数学家张 邱建在他的《算经》中提出了一个闻名于后世的百钱百鸡问 题:鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一, 百钱买百鸡,翁、母、雏各几何?
1.算法分析与设计 (1) 以三种鸡的个数为枚举对象,分别设为x,y,z。根据题 意,可以列出下面的不定方程