一.穷举算法的核心是什么?
我想要抓住两点:
1.多重循环(不能遗漏,也不能重复)。2.变量之间的关联。(分为数学上的关联和计算机上表现出来的关联。)
3.各变量的取值范围尽可能满足要求的情况下缩小。
二.算法举例
问题一: (百钱买百鸡问题)大约在公元5世纪,数学家张邱建在他的《算经》中提出了一个闻名于后世的百钱百鸡问题:鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一,百钱买百鸡,翁、母、雏各几何?
1.第一个问题,变量有哪些?
三个变量,x,y,z。
2.第二个问题,变量的数学关联和计算机编程时优化的关联?
x+y+z=100;5x+3y+1/3*z=100
以上是数据关联,我们面对第一个问题,三分之一在计算机里并不能很好的表示?第二个问题,变量x,y,z的变化范围?穷举算法特点是算法简单,但运行时所花费的时间量大。因此,我们在用穷举方法解决问题时,应尽可能将明显的不符合条件的情况排除在外,以尽快取得问题的解。 这样我们就要思考将一些数学关联优化成计算机喜欢的关联方式。
以下是关系式的转化过程:
x+y+z=100;15x+9y+z=300
可得:
7*x+4*y==100; z=100-x-y;
注:第一个关系式的变量x,y,z的取值范围在0~100;
第二个关系式的变量取值范围x是0~20,y是0~33;z是0~100;
最后一个关系式的变量取值范围是0≤x≤14,0≤y≤25.z是0~100;
#include<stdio.h>
void main()
{
int x,y,z;
for(x=0;x<=14;x++)
for(y=0;y<=25;y++)
if(7*x+4*y==100) //本来是三重循环现在优化成两重循环,并且变量范围缩小,循环次数也大大缩小。
{
z=100-x-y;
printf("x=%d,y=%d,z=%d\n",x,y,z);
}
}
问题二 : (谁做的好事)已知有有四位同学中的一位做了好事,不留名,表扬信来了之后,校长问这四位是谁做的好事。
A说:不是我。
B说:是C。
C说:是D。
D说:他胡说。
已知三个人说的是真话,一个人说的是假话。现在要根据这些信息,找出做了好事的人。
第一个问题数学关联?
这里不易找到纯数学的关联,但有逻辑上的关联。有4个关系表达式:
thisman!=‘A’
thisman==‘C’
thisman==‘D’
thisman!=‘D’
逻辑表达式的计算结果只有0(假)和1(真)两种结果。现在“已知三个人说的是真话,一个人说假话”,也就是表中的4个关系表达式中有3个是真的,1个是假的。
因此4个关系表达式的值的和应该等于3。定义变量cond表示四个关系表达式的和cond= thisman!=‘A’+ thisman==‘C’+ thisman==‘D’+thisman!=‘D’,那么,cond==3
#include<stdio.h>
enum goodman {A,B,C,D};
void EnumToGdman(enum goodman man)
{
switch(man)
{
case 'A': printf("做好事的人是:A");break;
case 'B': printf("做好事的人是:B");break;
case 'C': printf("做好事的人是:C");break;
case 'D': printf("做好事的人是:D");break;
}
}
void main()
{ enum goodman thisman;
int cond;
for(thisman='A'; thisman<='D';thisman++)
{
cond=(thisman!=‘A’)+(thisman==‘C’)
+(thisman==‘D’)+(thisman!=‘D);
if(cond==3)
EnumToGdman(thisman);
}
}