题目描述:
A、B、C、D、E五个学校,A说E是第一,B说B是第二,C说A是最差的,D说C不是最好的,E说D是最好的。只有第一和第二名说的是对的,其他说的都是错的,请编程确定五个学校的名次。
先上代码,再说思路。
代码:
#include <stdio.h>
int main() {
int a, b, c, d, e;
int val = 0;
int flag = 1;
int cnt = 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(((a == 2) && (e == 1)) +
(b == 2) +
(((c == 1) || (c == 2)) && (a == 5)) +
(((d == 1) || (d == 2)) && (c != 1)) +
(((e == 1) || (e == 2)) && (d == 1))
== 2) {
val = 0;
flag = 1;
cnt = 0;
val |= (1 << (a-1));
val |= (1 << (b-1));
val |= (1 << (c-1));
val |= (1 << (d-1));
val |= (1 << (e-1));
while(val) {
if(val%2 == 0)
flag = 0;
val /= 2;
cnt++;
}
if(flag == 1 && cnt == 5) {
printf("a=%d b=%d c=%d d=%d e=%d\n", a, b, c, d, e);
}
}
return 0;
}
思路:
每个学校的名次是1~5范围之间,所以采用5个for var=1 to 5的循环来表示每个学校的可能名次(这算是暴力破解吧,还请大神指正另外的思路)。在最内层循环中,利用if条件判断语句描述题目中的说法,例如:((c == 1) || (c == 2)) && (a == 5),该语句表示c若满足是第一名或第二名,那么c说的是真话,a此时就应该是最差的。比较特殊的有:1、(a == 2) && (e == 1),这是因为a == 1,若为真的话,e就不能为1;2、b == 2,b自己说自己是第二,要么是真话,要么是假话,也不能匹配其他条件。剩余的两个条件相信大家也能类似的推出来。
那么在这几个判断条件中,只有两个人说了真话,所以将这5个判断条件相加应该等于2,表示这五个条件中,有2个人说了真话。
进入if条件中后,我们用val的五个位分别表示每个学校可能的名次,只有满足val的后5位是全1的才能说明a、b、c、d、e分别隶属于不同的名次,不然肯定有某几个学校的名次是重合的。接下来我们就用while(val)循环判断val的后5位是否是全1。flag标志为0表示后5位某一位为0,不满足我们的条件。cnt是确保确实while循环执行了5次,因为在测试的过程中发现,仅根据flag标识会漏判末尾连续全1,但高位存在0的情况,比如:00001。
当判断最后5位全1的条件满足时,我们就输出符合条件的情况: