题目:
A选手说:B第二,我第三
B选手说:我第二,E第四
C选手说:我第一,D第二;
D选手说:C最后,我第三;
E选手说:我第四,A第一;
比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。
分析:
因为每个人说了2/5种情况,而只说对1/2
所以每个人说的情况正确的几率是1/5
五人说的都对的概率则为(1/5)^5=1/125
所以本题采用遍历所有情况求得
1.首先当然要给出所有的情况
2.因为每个人都是一个独立的个体,所以要创建一个数组来存放五个人说的话
设存放选手的数组为p,那么从p[0]~p[4]这五个元素则对应A B C D E五个人
3.而每个元素的值则对应该该选手的排名
例如p[3]=2,代表选手D排第2名
4.我们可以通过五个循环来遍历p[0]~[4],并且对p中元素的值进行修改
5.而每个人又给出了两种排名,其中只有一种是对的
例如A选手说:B第二,我第三;
那么p[1]==2和p[0]==3只有一个是对的
所以要对这两种情况进行判断,如果都对或都不对就不符合条件
书写方式为 if( (p[1]==2) + (p[0]==3) ) == 1
因为当p[1]==2成立,返回值为1,如果此时p[0]==3也成立,相加得2,不符合条件
通过这种方式可以对五个人说的话进行判断,如果每个人说的都只有一句是对的才进行后续操作
6.只判断每个人说的都只有一句是对的还不够,我们还要判断是不是有人的排名重复了,如果排名重复了也是不行的
这里要写一个函数判断排名是否重复,而且要和五个人说的话一起进行判断,如果六个条件都成立,才能确定真正的排名
我们可以设当排名不重复,函数返回值为1,当排名重复,函数返回值为0,这样和前面五个条件一起判断是就能通过&&来实现同时判断
在函数内部创建一个数组tmp,这个数组用来当做排名表,该表初始化为全0,代表该名次尚未有选手占用,如果未被占用,则把该排名的值改为1
例如tmp[1] = 0,代表第二名尚未被占用,tmp[3]=1,代表第四名已经被占用
每次写入新排名的选手时都要检查一下该排名是否已经被占用,如果该排名被占用(已经有选手了),说明排错了!要重新进行排名,所有排名都要重新进行,前面所有的假设都不成立,return 0;
当没有出现排名重复的情况,说明排对了,return 1;
7.当六个条件都成立的时候,就可以对排名进行打印了
源码:
int checkData(int* p)
{
//创建一个表,存放排名
int tmp[7] = { 0 }; //标记表,实际是哈希表的思路。一开始每个元素都是0。
//建立选手
int j;
//遍历该表
//tmp[p[0]]代表选手A的排名,例如p[0]==1,代表A是第一名为真,则tmp[p[0]]==tmp[1]==1,即第一名已经被占了
//tmp[p[3]]代表选手D的排名,若p[3]==2,代表D是第二名为真,则tmp[p[3]]==tmp[2]==1,即第二名已经确定了
for (j = 0; j < 5; j++)
{
//判断是否出现重复的排名
//如果某个名次的人员已经确定了,该名次的值为1
//此时如果发现还有一个人也可能是这个排名,因为每个名次只能给一个人,不能出现并列的情况,那么说明这两个人的排名有冲突,说明排错了
//排错了的话所有排名都要重新进行,前面所有的假设都不成立
if (tmp[p[j]])
{
return 0;
}
//当不出现重登排名的时候,把名次给占用,值改为1
tmp[p[j]] = 1;
}
return 1; //全部标记完毕也没有出现重复的情况,代表OK。
}
int main()
{
//x-1代表这种情况是选手x说的,p[x-1]的值代表选手x的名次
int p[5]; //0 1 2 3 4分别代表a b c d e
//通过循环实现125种情况
for (p[0] = 1; p[0] <= 5; p[0]++)
{
for (p[1] = 1; p[1] <= 5; p[1]++)
{
for (p[2] = 1; p[2] <= 5; p[2]++)
{
for (p[3] = 1; p[3] <= 5; p[3]++)
{
for (p[4] = 1; p[4] <= 5; p[4]++) //五层循环遍历
{
//这里是五个人的描述,由于比较表达式只有0和1两个结果,如果要两个条件有且只有一个为真,则可以用比较表达式的值总和为1的方式直接判定。别忘了还要判定不能并列。
//此处判断
//因为每个人说的两种情况只有一种是对的,所以当其中一个为真,返回值为1,当其中两个为真,返回值为2,都为假返回值为0
if ((p[1] == 2) + (p[0] == 3) == 1 && //A选手说:B第二,我第三
(p[1] == 2) + (p[4] == 4) == 1 && //B选手说:我第二,E第四
(p[2] == 1) + (p[3] == 2) == 1 && //C选手说:我第一,D第二
(p[2] == 5) + (p[3] == 3) == 1 && //D选手说:C最后,我第三
(p[4] == 4) + (p[0] == 1) == 1 && //E选手说:我第四,A第一
checkData(p) //不能并列
)
{
for (int i = 0; i < 5; i++)
{
printf("p[%d] = %d ", i, p[i]);
putchar('n');
}
}
}
}
}
}
}
return 0;
}



