[i=s] 本帖最后由 dchwlinux 于 2010-3-25 11:55 编辑 [/i]
五位跳水高手将参加十米高台跳水决赛,有好事者让五个人据实力预测比赛结果。
A选手说:B第二,我第三;
B选手说:我第二,E第四;
C选手说:我第一,D第二;
D选手说:C最后,我第三;
E选手说:我第四,A第一;
决赛成绩公布之后,每位选手的预测都只说对了一半,即一对一错,请编程解出比赛的实际名次。
思路:
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;
2 考虑到每个人说的话是一对一错,即一真一假,比如A说的,如B==2为真,则A==3为假,为真取值为1,为假取值为0,则两个关系表达式之和必为1。即(B==2)+(A==3)应该是1
我们可以归纳出要同时满足五个人所说的话都符合一半对一半错的条件是
ta=((B==2)+(A==3))==1;符合A选手的话,则ta为1
tb=((B==2)+(E==4))==1; 符合B选手的话,则tb为1
tc=((C==1)+(D==2))==1; 符合C选手的话,则tc为1
td=((C==5)+(D==3))==1; 符合D选手的话,则td为1
te=((E==4)+(A==1))==1; 符合E选手的话,则te为1
因为ta,tb,…,te非1即0,五个条件值都加在一起
0<=ta+tb+tc+td+te<=5
3 只有等于5时才都符合每个人所说的话,这仅只是符合题意的一个必要条件,同时还得考虑A、B、C、D、E的取值不得有相同者
a,b,c,d,e属于{1,2,3,4,5},且不相同
可以考虑a*b*c*d*e==120是一个条件
4 仍然可以用枚举的方法,让变量A、B、C、D、E在1~5中取值,形成满足上述条件的A~E的组合,即是所求。这时可用循环结构
我就是循环结构不会写


yzs 于 2010-03-26 08:30:25发表:
过来听楼上们讲课
charles-liu 于 2010-03-25 23:00:35发表:
不用判断等于120那个条件,因为在每层里都做了不相等的条件判断。
dchwlinux 于 2010-03-25 22:47:32发表:
8# hantu
你的意思我看懂了,不过题中说的a*b*c*d*e=120那个条件怎么用啊?不是说要判断五个变量不相等要用到这个条件吗?你写的方法也是一种方法。还有说到优化,怎么个优化法?你有什么高见?
xborong 于 2010-03-25 21:32:10发表:
:0wpoi2
hantu 于 2010-03-25 18:58:51发表:
因为计算没有很多,所以尽管没有做优化,一运行也马上得到结果:
a=3 b=1 c=5 d=2 e=4
hantu 于 2010-03-25 18:42:53发表:
楼主所想的是直接简单的算法,虽然效率较低,但能奏效。代码如下,试一下吧:
#include
main()
{
int a,b,c,d,e;
for(a=1;a<=5;a++){
for(b=1;b<=5;b++){
if(b==a)continue;
for(c=1;c<=5;c++){
if(c==b||c==a)continue;
for(d=1;d<=5;d++){
if(d==c||d==b||d==a)continue;
for(e=1;e<=5;e++){
if(e==d||e==c||e==b||e==a)continue;
if(((b==2)+(a==3))==1 && ((b==2)+(e==4))==1 && ((c==1)+(d==2))==1 && ((c==5)+(d==3))==1 && ((e==4)+(a==1))==1){printf("a=%d b=%d c=%d d=%d e=%d\n",a,b,c,d,e);exit(0);}
}
}
}
}
}
}
dchwlinux 于 2010-03-25 18:39:54发表:
那个穷列举法怎么做?五个for罗列在一块儿?
zelda 于 2010-03-25 18:00:53发表:
。。。。这对我也复杂
hongyu315 于 2010-03-25 17:17:02发表:
呵呵 对我而言有点复杂
dchwlinux 于 2010-03-25 16:42:12发表:
那五重循环怎么做的?
alick 于 2010-03-25 12:33:32发表:
就是五重循环吧,最里面一层做判断