前言
本文中博主将一步一步地、以正常人的顺序思维完成题目——费解的开关,使用的核心方法是递推与递归。
题目
参考题目:费解的开关
(资料图)
详细的题目信息相信大家都已经知道了,因此这里为了简洁只展示输入输出格式及数据范围。
核心思维
本题利用递推做的核心思想很简单,即当这个5x5数组的第一行被处理完过后,想要开启第一行仍然灭着的灯,则必须点击该灯的下一行的相同位置。
因此,只要确定好第一行如何选择,其他行也自然确定了,之需要判断该种情况是否满足题目条件即可。
如图所示:
假设我们第一行只点一次,即被蓝色X的地方,点完后会变成这样:
如果我们想让第一行的第一个、第四个变亮,那么第二行的第一个、第四个就是必点的。
因此,我们只需要枚举第一行的所有选法,然后就能递推出整个四方体的选法,最后判断成是否成立。
写出数据输入格式
首先,先在主函数里写出题目要求的输入格式。先输入一个n,随后进行n次循环,每次循环都读入25个数据放在一个二维数组arr里。为了传参的时候方便,我们把二维数组放在外面,像这样:
int arr[5][5];int main(){int n = 0;scanf("%d", &n);while (n--){int i = 0;for (i = 0; i < 5; i++){int j = 0;for (j = 0; j < 5; j++){scanf("%1d", &arr[i][j]);}}//...}return 0;}
注意:本题在Acwing上数据输入时,每个数据之间没有空格,因此要控制scanf每次读取数据的宽度。代码中的“//...”代表接下来从此处开始写。
枚举第一行的选择
这里我们使用递归的方法,即在1 ~ 5里面选出1 ~ 5个数,每一种选法都是一种第一行的选择。创建递归函数dfs(int step),step代表当前枚举的位置,在外面创建数组choose代表递归时每个位置的状态,每次枚举当前位置选或者不选,五个位置都枚举结束后就代表形成了一种情况,随后利用判断函数jud对这种情况进行判断。
int main(){//...dfs(0);//dfs的位置}return 0;}
int arr[5][5];int choose[5];void dfs(int step){if (step == 5){jud(choose);return;}//选choose[step] = 1;dfs(step + 1);choose[step] = 0;//不选dfs(step + 1);}
判断情况是否成立(1)
随后我们进行判断函数jud的书写,为了防止同一组数组不同的情况互相影响,我们创建一个临时的数组 arr,复制arr的信息到其中,随后对 arr进行操作。
之后创建i和j,分别用于遍历行和列。
由于i和j的值不同,点灯还是灭灯的个数也不同(因为有可能在边界)。因此,我们创建一个函数change,用于改变arr【i】【j】周围能改变的灯的亮灭情况。
void jud(int* choose){int _arr[5][5];memcpy(_arr, arr, 25 * 4);//对第一行进行操作int i = 0;//用于遍历行int j = 0;//用于遍历列for (j = 0; j < 5; j++){if (choose[j] == 1)//相当于arr【0】【j】被选择了{change(_arr, 0, j);//...}}}
实现亮灭改变函数
罗列情况,改变周围灯的亮灭情况,如果你不想写这么多的代码,也可以把刚开始创建的数组改为7x7大小,就可以不用考虑边界了。
void change(int _arr[5][5], int i, int j){_arr[i][j] = !_arr[i][j];if (i == 0){_arr[i + 1][j] = !_arr[i + 1][j];if (j == 0){_arr[i][j+1] = !_arr[i][j+1];}else if (j == 4){_arr[i][j-1] = !_arr[i][j-1];}else{_arr[i][j - 1] = !_arr[i][j - 1];_arr[i][j + 1] = !_arr[i][j + 1];}}else if (i == 4){_arr[i - 1][j] = !_arr[i - 1][j];if (j == 0){_arr[i][j + 1] = !_arr[i][j + 1];}else if (j == 4){_arr[i][j - 1] = !_arr[i][j - 1];}else{_arr[i][j - 1] = !_arr[i][j - 1];_arr[i][j + 1] = !_arr[i][j + 1];}}else{_arr[i - 1][j] = !_arr[i - 1][j];_arr[i + 1][j] = !_arr[i + 1][j];if (j == 0){_arr[i][j+1] = !_arr[i][j+1];}else if (j == 4){_arr[i][j - 1] = !_arr[i][j - 1];}else{_arr[i][j - 1] = !_arr[i][j - 1];_arr[i][j + 1] = !_arr[i][j + 1];}}}
判断情况是否成立(2)
因为对第一行的每一次选择也算走了一步,所以在每种情况下设置一个变量time,记录当前走了几步,一旦time超过6,就立马return。
注意:第一行只有五个数,因此在第一行的选择中time不可能超过6,因此不需要在对第一行的选择中进行判断。
void jud(int* choose){int _arr[5][5];memcpy(_arr, arr, 25 * 4);int time = 0;//对第一行进行操作int i = 0;//用于遍历行int j = 0;//用于遍历列for (j = 0; j < 5; j++){if (choose[j] == 1)//相当于arr【0】【j】被选择了{time++;change(_arr, 0, j);}}//...//对2,3,4,5行进行操作}
随后对第2,3,4,5行进行选择,对第二行的选择次数,是源于第一行选择完之后还有几个灭着的灯。
因此,我们对上一行进行遍历,如果_arr【i-1】【j】==0,就把time+1,同时点一下_arr【i】【j】。
注意:此时,time已经有可能超过6了,因此需要进行判断。
void jud(int* choose){int _arr[5][5];memcpy(_arr, arr, 25 * 4);int time = 0;//对第一行进行操作int i = 0;//用于遍历行int j = 0;//用于遍历列for (j = 0; j < 5; j++){if (choose[j] == 1)//相当于arr【0】【j】被选择了{time++;change(_arr, 0, j);}}//...//对2,3,4,5行进行操作for (i = 1; i < 5; i++){for (j = 0; j < 5; j++){if (_arr[i - 1][j] == 0){time++;if (time > 6){return;}change(_arr, i, j);}}}//...}
现在,我们已经对1 ~ 5行全部选择完毕,但是不确定是否全部都为1,因此需要进行遍历一次,一旦出现为0的情况,说明这种情况不可取,马上返回。
//检测数组中是否全部为1for (i = 0; i < 5; i++){for (j = 0; j < 5; j++){if (_arr[i][j] == 0){return;}}}//...//运行到这里,说明此种方案可行
对输出数据的处理
题目要求我们输出所有可行的方案中步数最少的一种所消耗的步数,如果没有可行方案则返回-1。
因此,我们设置一个全局变量min_time并令其初始化为一个大于6的数,一旦出现一个time小于min_time,就把min_time更新为time。
如果还有更小的time,就能再次更新。
int arr[5][5];int choose[5];int min_time = 10;
//运行到这里,说明此种方案可行min_time = time;return;//...
随后,我们进行最后的处理。
当dfs(0)结束之后,我们得到了一个min_time,因为它的初始值大于6,所以只要有可行方案存在,该值就一定会被改变,否则,它就依然还是原来的值。
所以,我们设置一个if语句,如果该值为10(初始值),代表没有可行方案,打印-1后换行。
如果该值不等于10,就打印这个数后换行,代表最小步数为该值。
注意:因为min_time是我们在全局定义的,因此打印完了以后不要忘记再将其重新赋值为10哦。(博主改了很久才想到这一点,TAT)
int main(){int n = 0;scanf("%d", &n);while (n--){int i = 0;for (i = 0; i < 5; i++){int j = 0;for (j = 0; j < 5; j++){scanf("%1d", &arr[i][j]);}}dfs(0);if (min_time == 10){printf("-1\n");}else{printf("%d\n", min_time);min_time = 10;}}return 0;}
感谢您的阅读与耐心~ 如有错误烦请指出~
标签: 编程算法
-
世界今日报丨一步一步地完成题目——费解的开关(C/C++语言)递推、递归、顺序思维
本文中博主将一步一步地、以正常人的顺序思维完成题目——费解的开关,使用的核心方法是递推与递归。
-
全球快消息!美国白宫通信联络办公室主任将于本月底离职
当地时间2月10日,根据白宫发布的声明,白宫通信联络办公室主任凯特·贝丁菲尔德(KateBedingfield)将于2
-
天秤座男生性格_天秤座是几月几号到几月几号_环球快播报
1、天秤座[9月23日-10月22日]。本文到此分享完毕,希望对大家有所帮助。
-
向往的生活书包精彩线 书包精彩线是什么菜? 世界今头条
近日网络 "书包精彩线 "这个词火了,那么在向往的生活说的书包精彩线到底是什么呢?书包精彩线是什么菜呢?下面我们来一起介绍下吧!书包精彩...
-
伦纳德和乔治招募威少,快船队有望迎来威少
洛杉矶快船队在当家球星伦纳德和保罗乔治的带领下,目前来到31胜27负。暂时排在西部联盟第6位。自从洛杉矶快船队不敌达拉斯独行侠队,洛杉矶快
-
东莞实验中学地址_关于东莞实验中学地址的介绍-环球聚看点
1、东莞实验中学位于交通便利的东城区东宝路,创办于1993年,是一所建筑气派新颖,校园环境幽雅,教学设备先进的花园式高级中学,省级重点中学
-
埃迪-豪谈FFP:曼城的违规案能够更好地解释我们明智的转会策略:热点在线
纽卡斯尔主帅埃迪-豪在赛前的新闻发布会上,被问及曼城违反FFP面临处罚的问题。埃迪-豪:“我一直说FFP对我们来说是真实存在的。老板们一直很
-
电商软文代写
首先就是各种媒体抢占眼球竞争激烈,人们对电视、报纸的硬广告关注度下降,广告的实际效果不再明显,软文炒作是生命力最强的一种广告形式,也
-
北京脑中心Yamanaka实验室招聘实验室技术员---Open Lab Technician Position 今日讯
>>>中心简介北京脑科学与类脑研究中心(以下简称北京脑中心)由北京市政府与中国科学院、北京大学、清华大学等国内顶尖研究所 高校联合共...
-
特定物之债与种类物之债的定义和分类
导读:在我们的日常生活中,债权债务一般是不会单独出现的,有债权就一定会有债务,那么你知道特定物之债与种类物之债的定义和分
-
国美零售债台高筑逾期贷款约30亿 押注直播填补百亿负债但平台、主播、产品均无竞争力:环球热头条
出品:新浪财经上市公司研究院 距离黄光裕表示要用18个月时间重振国美、找回曾经市场地位,已过去整整两年时间。 两年以来,国美零售经
-
环球即时:cad2006序列号激活码_cad2006序列号
1、tocad2006激活码CAD2006序列号:191-75444444授权码:DAH4CT2SZVNUS
-
巴中市恩阳区聚焦痛点难点 优化营商环境
在四川省巴中市恩阳区临港产业园内,排着队的货车“空进满出”,装车机械起降有序……永润欣科技有限公司总经理凌选终于放下心来
-
淘宝怎么确认收货 每日视讯
淘宝怎么确认收货,淘宝怎么确认收货我们一起看看吧
-
情侣过第一个情人节送什么礼物|每日观点
情侣过第一个情人节送的礼物,情侣衫,代表着爱着甜蜜。如果是情侣,送男士手表的含义非凡的,不管什么人都会很高兴。情侣过一个
-
火爆!企业上火车“抢”人,月薪高达2万元!没下火车,工作到手
企业忙着招揽人才,务工人员专列也是他们瞄准的地方,在一趟广州开往宁波的火车上,不少“打工人”还没下火车,新工作就到手了。 在广州...
-
电动绑钩器怎么绑鱼钩_绑钩器怎么绑鱼钩
1、先把鱼钩放入绑钩器,然后拧紧螺母,把鱼线掺在后面的铁丝上。2、小拇指夹着长线,大拇指和无名指捏着短线缠绕。3、缠大概
-
今日热门!照片大小怎么改到20kb以上_照片大小怎么改到20k
1、在下面出现的选项框中单击“导出”,然后在右侧的菜单栏中选择“以Web格式保存”。在弹出窗口中,单击预设右侧的优化菜单图标,并在弹出...
-
物流管理系统软件哪个好_物流管理系统
1、如今是数字化信息时代,企业想要在物流管理方面打好基础就必须要紧跟时代潮流,将数字化运用到物流管理上去。2、其中搭建数
-
日产商务车7座最新_日产商务车7座有哪些:环球速递
1、七座日产商用车有三款,分别是东风日产骏逸、郑州日产NV200、日产诗鬼。2、日产是一家业务涵盖汽车制造、造船和航空航天技术的公司。3、它
-
老人带孙在地铁车厢内小便!工作人员:每个站点均配有洗手间
三湘都市报·新湖南客户端2月9日讯(文 视频全媒体见习记者王翊玮 通讯员 李如洋)2月7日,一名长沙网友上传了一段视
-
nvidia geforce gt 630m怎样 速递
1、梅捷是一个牌子,GT630是显卡的型号,一个牌子可以生产很多型号的产品。2、梅捷也是属于比较低端的显卡牌子,卖家没必要哄你的,只不过GT63
-
长亮科技董事王长春减持57.18万股 减持金额711.32万元
每经AI快讯,据深交所官网,2023年2月8日,长亮科技(SZ300348,收盘价:12 84元)董事王长春通过竞价交易,减持公司57 18万股,成交均价12 44元
-
梦幻西游情侣游戏名字大全 焦点精选
游戏中的男女玩家都有取情侣名字的习惯,然而一个情侣名字也代表着彼此的身份,会让很多单身的玩家而羡慕。那么如何取个好听的梦
-
天天最资讯丨女朋友过生送什么礼物,充满创意精选清单
一般大家都不为小事而心动,但是见了些独特礼品,他们还是会很开心喔。说到创意送礼,朋友你们了解送女朋友什么好吗?女朋友过生
-
江苏雷利(300660.SZ)2022年度扣非净利润预增40%-55%、产品毛利率环比持续改善
格隆汇2月9日丨江苏雷利(300660)(300660 SZ)公布,预计2022年度归属于上市公司股东的净利润2 56亿元-2 93亿元,同比增长5%-20%;
-
孙叔敖举于海的故事简短_孙叔敖举于海的故事-世界今热点
1、孙叔敖举于海的意思是孙叔敖从海滨隐居的地方被起用。2、出自《生于忧患,死于安乐》。3、2、据今2600多年。4、楚
-
尿尿怎么读 尿尿的正确读法_全球新要闻
1、正确的读法是niaosui。2、首先纠正的是尿尿的读法niaoniao是错误的。3、输入新华字典。输入尿尿两个字点击查询。会看到正确的拼音是niaosui。
-
午间公告:大禹节水联合预中标重庆市长寿区桃花河流域环境综合治理项目
证券时报e公司讯,①大禹节水(300021):公司全资子公司甘肃大禹节水集团水利水电工程有限责任公司与中国葛洲坝(600068)集团股份有限公司(联合
-
全球信息:360推广账号登陆入口_360推广入口
1、你是说进入你自己的推官账户后台么?点睛平台:e 360 cn 帐号是自己当时的开户邮箱,另外建议你联系一下当时跟你