1.
5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果
A选手说:B第一,我第三。
B选手说:我第二,E第四。
C选手说:我第一,D第二。
D选手说:C最后,我第三。
E选手说:我第四,A第一。
比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。
题目要求是用编程实现,一开始拿到这个题目,真是两眼一抹黑无从下手的感觉,由实际问题抽象到具体问题对于我这种编程新手来说真的有点困难,于是我参考了别人的答案,才明白了怎么做。
他们将问题转化为逻辑判断,比如a选手说的”b第一,我第二”可以写成((b == 1) + (a == 3) == 1)这样子就满足题目每个选手都说对一半的要求(如果前半句是对的,那么有(b == 1)成立,于是(a == 3)就不成立了,两个逻辑结果相加为1,否则后半句对,(b == 1)不成立,(a == 3)成立,两个逻辑结果依旧相加为1)。同理其他选手也是这样写,最后再套用五重循环遍历所有情况,
当((b == 1) + (a == 3) == 1) &&
((b == 2) + (e == 4) == 1) &&
((c == 1) + (d == 2) == 1) &&
((c == 5) + (d == 3) == 1) &&
((e == 4) + (a == 1) == 1)
满足时候输出结果。
代码如下
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 0, b = 0, c = 0, d = 0, e = 0;
for (a = 1; a <= 5; a++) {
for (b = 1; b <= 5; b++) {
for (c = 1; c <= 5; c++) {
for (d = 1; d <= 5; d++) {
for (e = 1; e <= 5; e++) {
if (((b == 1) + (a == 3) == 1) &&
((b == 2) + (e == 4) == 1) &&
((c == 1) + (d == 2) == 1) &&
((c == 5) + (d == 3) == 1) &&
((e == 4) + (a == 1) == 1)) {
//int num = 0;
//num |= 1 << (a - 1);
//num |= 1 << (b - 1);
//num |= 1 << (c - 1);
//num |= 1 << (d - 1);
//num |= 1 << (e - 1);
//while (num) {
// if (num % 2 == 0)
// break;
// else
// num = num >> 1;//num /=2;
//}
//if (num == 0)
printf("a=%d,b=%d,c=%d,d=%d,e=%d\n", a, b, c, d, e);
}//if
}
}
}
}
}
system("pause");
return 0;
}
代码跑完会输出很多种情况,并列名次是可以的比如11234,12234,但是这种13334显然不符合实际情况,为此我们要保证名次连续(名次可重复如上所说),不妨用二进制的位运算。设置一个num = 0,num的二进制为0000 0000
如果存在第一名就让最后一位为1,即0000 0001
如果存在第二名就让倒数第二为为1,即0000 0010
同理存在第三名即0000 0100等
如果都连续的话,即00001111,0001 1111等说明他们名次连续。
那么如何置1?可以考虑用或运算
例如0000 0000 | 1 = 0000 0001
0000 0000
0000 0001
通过或运算得到0000 0001。
这只是存在第一名的情况,若存在第二名即让倒数第二位为1
0000 0000
0000 0010
通过或运算得到0000 0010。
若存在第三名,就让倒数第三位为1
0000 0000
0000 0100
通过或运算得到0000 0100
可以看出只要将1的二进制数左移再和num进行或运算即可
0000 0001(1的二进制数)
0000 0010(左移1位)
0000 0100(左移1位)
所以若 a = 1的话,num |= 1 << 0
a = 2的话 num |= 1 << 1
a = 3的话 num |= 1 << 2
即num |= 1 << (a - 1)
同理 num |= 1 << (b - 1)
num |= 1 << (c - 1)
num |= 1 << (d - 1)
num |= 1 << (e - 1)
这样得到num序列,比如是上面的13334排名即num = 0000 1101
num % 2得到二进制的最后一位,如果是1说明这个名次存在
num / 2去除当前二进制的最后一位
判断名次的代码如下
while(num) {
if(num % 2 == 0) {
break;
num = num / 2; //num >> 1
}
if(num == 0)
printf("a=%d b=%d c=%d d=%d e=%d\n", a, b, c, d, e);
}
如果num跑完循环是0的话说明名次是连续的,不然必不连续,比如0000 1101,当遇到倒数第二位的时候为0跳出循环此时num = 0000 11
综上完整正确的代码去掉之前代码的注释就好了。
2.
日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。以下为4个嫌疑犯的供词。
A说:不是我。
B说:是C。
C说:是D。
D说:C在胡说
已知3个人说了真话,1个人说的是假话。
现在请根据这些信息,写一个程序来确定到底谁是凶手。
有了第一题的基础,第二题就简单多了,用逻辑判断(四个人所说的话逻辑和==3)即可,代码如下
#include <stdio.h>
#include <stdlib.h>
int main()
{
int killer = 'a';
for (; killer <= 'd'; killer++) {
if ((killer != 'a') + (killer == 'c') + (killer == 'd') + (killer != 'd') == 3) {
printf("killer=%c\n", killer);
}
}
system("pause");
return 0;
}
更多推荐
一些好玩的题目
发布评论