博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言应用题——如何确定跳水排名
阅读量:4149 次
发布时间:2019-05-25

本文共 3407 字,大约阅读时间需要 11 分钟。


问题描述


问题是这样的:

1


思考


首先,某人比赛的名次一定可能是1-5中的任意一个。所以得用5个for循环来实现

其次,这5个人的话都不是只关于自己,而且还有关于别人的。所以上边的5个for循环一定不能是各自独立的。他们得相互嵌套起来,形成约束

最后,每个人的话都只说对了一半,所以可以用if语句来判断。

这样,我们就可以写出代码了。


Code (v1.0)


#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;}

运行代码:

2

很显然,这是不合理的。排名只可能有一种,而且应该是连续的数字,上边的结果有的没有第一名,有的中间缺少第二名。只有第一种结果看起来比较合理。

所以网上有人想出了这种解决办法:

{                        printf("a= %d, b= %d, c= %d, d= %d, e=%d\n", a, b, c, d, e);                        system("pause");                        return 0;            }

即在printf之后直接返回,这样程序结果就变成:

3

结果居然出来了。

但是,这种办法是一种投机取巧的做法,在代码中加return 0,使其只输出第一个结果就返回,当然不可取

那么这个问题到底怎么解决呢?


Solution


人类的智慧是无穷的,此路不通,自会开辟新经。

下面博主给大家安利一种解法,当然,这不是我的原创。如果你有更好的办法,请在下方留言,或者私信我告诉你的做法。本人不胜荣幸。

俗话说,解铃还须系铃人。要想得到解决办法,必须要找到问题。

我们再来思考一下这个问题:

刚才程序运行出的结果有很多,但我们知道,正确的结果应该只有一个,所以问题的关键在于如何过滤掉其他的错误结果

其实这个问题还有两个隐形的约束条件:

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。然后根据排名对其比特位中的数值做以下更改:

4

这样一来,如果a,b,c,d,e的名字是连续的话,其低位的比特位就全是1.

所以我们可以得到解决办法:

先通过a,b,c,d,e的名字将ret中对应比特位置1,然后判断其低位有没有夹杂0。有0的结果就可以被我们过滤掉了。

至于如何对比特位进行操作使其置1,又如何判断0.可以看这篇博文:


Code(V2.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);                        }

之后运行代码,就可以得到如下结果:

5

可以看到,不用上边投机取巧的做法,我们也能得到正确的结果。

你可能感兴趣的文章
经典Android开发教程!面试字节跳动两轮后被完虐,附面试题答案
查看>>
经典实战教程!闭关60天学懂NDK+Flutter,值得收藏!
查看>>
给Android程序员的一些面试建议,实战解析
查看>>
给Android程序员的一些面试建议,已开源
查看>>
网易资深安卓架构师:Android开发经验的有效总结,醍醐灌顶!
查看>>
网络优化软件apk,金九银十怎么从中小企业挤进一线大厂?我先收藏为敬
查看>>
美团Android开发工程师岗位职能要求,知乎上已获万赞
查看>>
android结束进程,卧薪尝胆70天内推入职阿里,附答案
查看>>
android自学教程!BAT等大厂必问技术面试题,BAT大厂面试总结
查看>>
Android自定义View详解,知乎上已获万赞
查看>>
android路由器app,Android权限处理,2年以上经验必看
查看>>
android路由表,我了解到的面试的一些小内幕!附超全教程文档
查看>>
android路由跳转,Android面试资料集合,完整PDF
查看>>
android进程共享,记一次字节跳动Android社招面试,全网最新
查看>>
Android进程管理,有了这些中高端面试专题-大厂还会远吗?使用指南
查看>>
android适配屏幕大小,Android-MVP模式详解,全网疯传
查看>>
Android面试中常问的MMAP到底是啥东东?终局之战
查看>>
Android开发者跳槽面试,积累总结
查看>>
Android开发者面试如何系统复习?帮你突破瓶颈
查看>>
android开发面试题,分享一些行业经验,写给正在求职的安卓开发
查看>>