忘记排名?算法伺候
问题:
在一次竞赛中,A、B、C、D、E 等五人经过激烈的角逐,
最终取得了各自的名 次,他们的一个好朋友很遗憾没有观看到比赛,
在比赛结束后这个朋友询问他们 之间的名次是得知:
C 不是第一名,D 比 E 低二个名次,而 E 不是第二名,
A 即不是第一名,也不是最后一名,B 比 C 低一个名次。
编写程序,计算这五个人各自的名次并输出
提示:D比E低二个名次,那D和E的位置肯定是在(1,3)、(2,4)、(3,5)而E不是第二名,后面还有其他条件的限制。
人脑算的话,假设A,B,C,D,E,这排名就是这样排的,拿纸笔或者电脑画图几分钟就套出来,但我们是让计算机算。
穷举算法伺候
脑算的话
这是一组组合
A B C D E
A B C E D
A B D E C
A B D C E
A B E C D
A B E D C
加上这一组合后面的C、D、E这样的话6×4=24 24×5=120,A是第一的可能就有24种,总共有120种组合。
假设A,B,C,D,E,A是第一名,A的全部可能遍历完之后,在把B当做第一名,后面一次类推,A,B,C,D,E,定义一组字符数组,然后再弄个for循环往里面套,一组组合传进字符数组后,最后再加个条件,条件就是问题,一组组合传进去,就判断条件,不是就下一次组,直到全部遍历完。
代码实现:
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<Windows.h>
int logic_reasoning(char str1_tmp[5]){
//返回值说明:0代表假1代表真
//判断一. C不是第一名
if(str1_tmp[0]=='C')return 0;
//判断二. D比E低二个名次
int flag =0;//标记
for(int k=0;k<3;k++){
if(str1_tmp[k]=='E' && str1_tmp[k+2]=='D'){
flag = 1;
}
else continue;
}
if(flag==0) return 0;//假 调回返回0
//判断三. E不是第二名
if(str1_tmp[1]=='E') return 0;
//判断四.A即不是第一名,也不是最后一名
if(str1_tmp[0]=='A'||str1_tmp[4]=='A') return 0;
//判断五.B 比 C 低一个名次
flag=0;//初始化标记
for(int k=0;k<4;k++){
if(str1_tmp[k]=='C'&&str1_tmp[k+1]=='B'){
flag=1;
}
else continue;
}
if(flag==0) return 0;
return 1;//推理完成返回真 1
}
int main(void){
char str1[5]={'A','B','C','D','E'};
char tmp[5];//存放计算后的五人名次
memset(tmp, '\0', sizeof(char) * 5);//清空内存
//A i0=0;
for(int i0=0;i0<5;i0++){
tmp[0]=str1[i0];
//B i1=1;
for(int i1=0;i1<5;i1++){
if(i1==i0){continue;}
tmp[1]=str1[i1];
//C i2=2;
for(int i2=0;i2<5;i2++){
if(i2==i0||i2==i1){continue;}
tmp[2]=str1[i2];
//D i3=3;
for(int i3=0;i3<5;i3++){
if(i3==i0||i3==i1||i3==i2){continue;}
tmp[3]=str1[i3];
//E i4=4;
for(int i4=0;i4<5;i4++){
if(i4==i0||i4==i1||i4==i2||i4==i3){continue;}
tmp[4]=str1[i4];
if(logic_reasoning(tmp)){
printf("已完成您的结果:\n");
for(int i=0;i<5;i++){
printf(" %c ",tmp[i]);
}
printf("\n");
}
}
}
}
}
}
system("pause");
return 0;
}