本文共 3407 字,大约阅读时间需要 11 分钟。
问题是这样的:
首先,某人比赛的名次一定可能是1-5中的任意一个。所以得用5个for循环来实现。
其次,这5个人的话都不是只关于自己,而且还有关于别人的。所以上边的5个for循环一定不能是各自独立的。他们得相互嵌套起来,形成约束。
最后,每个人的话都只说对了一半,所以可以用if语句来判断。
这样,我们就可以写出代码了。
#define _CRT_SECURE_NO_WARNINGS#include#include int main(){ //a.b.c.d.e均可能是1-5名,为了方便表示其关联关系,形成for循环嵌套 for (int a = 1; a <= 5; a++) { for (int b = 1; b <= 5; b++) { for (int c = 1; c <= 5; c++) { for (int d = 1; d <= 5; d++) { for (int 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)) //所有的条件都只有1个为真 { printf("a= %d, b= %d, c= %d, d= %d, e=%d\n", a, b, c, d, e); } } } } } }system("pause");return 0;}
运行代码:
很显然,这是不合理的。排名只可能有一种,而且应该是连续的数字,上边的结果有的没有第一名,有的中间缺少第二名。只有第一种结果看起来比较合理。
所以网上有人想出了这种解决办法:
{ printf("a= %d, b= %d, c= %d, d= %d, e=%d\n", a, b, c, d, e); system("pause"); return 0; }
即在printf之后直接返回,这样程序结果就变成:
结果居然出来了。
但是,这种办法是一种投机取巧的做法,在代码中加return 0,使其只输出第一个结果就返回,当然不可取。
那么这个问题到底怎么解决呢?
人类的智慧是无穷的,此路不通,自会开辟新经。
下面博主给大家安利一种解法,当然,这不是我的原创。如果你有更好的办法,请在下方留言,或者私信我告诉你的做法。本人不胜荣幸。
俗话说,解铃还须系铃人。要想得到解决办法,必须要找到问题。
我们再来思考一下这个问题:
刚才程序运行出的结果有很多,但我们知道,正确的结果应该只有一个,所以问题的关键在于如何过滤掉其他的错误结果
其实这个问题还有两个隐形的约束条件:
1.排名的名次应该是连续的,比如第一名和第三名中间一定要有第二名。
2.排名的名次必须并且从开始,不能没有第一名,直接从第二名开始,比如:无重名:1 2 3 4 5
有重名::1 2 2 3 4 /1 2 3 3 4这样的结果就一定是错误的:2 2 3 4 5
所以解决问题的矛头又指向了如何判断一个结果是否满足上边的2个条件。
其实,这两个条件不需要分别判断,可以用一个方法同时判断。
首先,假设跳水排名为:a = 4, b = 2, c = 3, d = 1, e = 1.然后我们定义一个int 型的数据ret,初始化为0。然后根据排名对其比特位中的数值做以下更改:
这样一来,如果a,b,c,d,e的名字是连续的话,其低位的比特位就全是1.
所以我们可以得到解决办法:
先通过a,b,c,d,e的名字将ret中对应比特位置1,然后判断其低位有没有夹杂0。有0的结果就可以被我们过滤掉了。
至于如何对比特位进行操作使其置1,又如何判断0.可以看这篇博文:
利用上边的思想,我们对for循环最里层的代码做出如下改善:
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)) //所有的条件都只有1个为真 { int ret = 0; //置位 ret |= (1 << (a - 1)); ret |= (1 << (b - 1)); ret |= (1 << (c - 1)); ret |= (1 << (d - 1)); ret |= (1 << (e - 1)); //判断低位中是否夹杂了0 while (ret)//直到所有比特位全判断完成才退出 { if (ret % 2 == 0) { break; } ret /= 2; } if (ret ==0)//ret不断/2最终为0时就说明已经判断完了 printf("a= %d, b= %d, c= %d, d= %d, e=%d\n", a, b, c, d, e); }
之后运行代码,就可以得到如下结果:
可以看到,不用上边投机取巧的做法,我们也能得到正确的结果。