C:勇敢羊羊不怕困难!2022-2023年度第四届全国大学生算法设计与编程挑战赛(秋季赛)之羊驼
目录
题目分析
程序设计
总体流程
信息输入
递归函数
完整代码
代码分析
题目分析
问题描述如图:
利用函数迭代,找出能走到出口的每一条路,取路径最短的路线。
程序设计
总体流程
- 输入相应的地图信息。
- 从初始位置开始,向四个方向试探(不超出边界)。
- 若试探位置没有陷阱,以该位置作为新的起始点重复流程(应该把来路设置为有陷阱避免反复横跳)。
- 若试探位置有陷阱,换个方向进行试探。
- 位于死胡同时(各个方向均无路可走),返回上一步所在位置,试探该位置的其他方向。
- 走到终点时,记录所用步数,与历史最少步数比较,保留最小值。退后若干步试探新的路线。
- 将所有走法试探一遍后,结束试探,输出最小步数。
信息输入
为方便递归函数调用,将地图基本信息声明为全局变量:
#include<stdio.h>
int n,m,a,b,x,y;
在试探的函数递归中将不断用到其中某些数据而不更改其值,将其定义为全局变量可以减少程序运行时间和内存占用。
在主函数中输入数据:
int main(){scanf("%d %d",&n,&m);scanf("%d %d %d %d",&a,&b,&x,&y);a--;b--,x--,y--;//行列标号变为数组索引int map[n][m];for(int i=0;i<n;i++){for(int j=0;j<m;j++){scanf("%d",&map[i][j]);}}/*计算部分*//*结果输出部分*/
}
输入的起点、终点坐标是序号值,输入后转化为索引值便于后续使用。根据输入的尺寸声明地图数组map并分配空间,使用嵌套循环依次输入陷阱分布。
在使用scanf()函数接收键入的数据时,空格与换行符都用于分隔若干段数据,循环每次只输入一个数字,但每次输入并不一定需要用回车做分离,可以满足题目要求的按行输入,更为直观。
在各个数组的赋值、访问过程中,需注意序号与索引的变化,多维数组需注意行列对应的维度以及坐标轴的方向。
递归函数
定义最小步数、坐标增量数组(均为全局变量):
int min=2147483647;
int det[2][4] = {{1,-1,0,0},{0,0,1,1}};
每当走到出口时,将所用步数与min进行比较,赋予min其中的最小值,min的初始化赋予int类型的最大值,保证了在第一次找到出口后min总能被赋予该次所用的步数。
数组det表示行坐标或列坐标的各个增量,第一个维度表示行或列、第二个维度表示某一方向上的增量,四组增量分别为(1,0)、(-1,0)、(0,1)、(0,-1),即向下、向上、向右、向左。定义del的意义在于方便递归函数用一个循环就可以遍历四个方向。
声明用于递归的函数并实现其功能:
int rushB(int map[n][m],int R,int C,int step){//遍历四个方向for(int i=0;i<4;i++){int r=R+det[0][i],c=C+det[1][i];//试探位置的索引/*走到出口执行的操作*//*非出口但可走执行的操作*/}return 0;//位于死胡同,结束该函数返回上一步
}
函数参数中数组map是陷阱分布地图,坐标R,C分别为此时所在位置行列的索引,整型数step为此时已经走过的步数。在参数的传递上,每个正在递归的rushB()函数与主函数main()里的数组map都指向同一个地址,在递归过程中不会占用内存,于任一函数中更改map的值后在其他函数中访问的也是更改后的值。
坐标r,c分别是试探位置行列的索引,会在后续操作中反复使用,将其定义为变量可以减少程序运算量,同时提高代码可读性。
走到出口时的操作如下:
int rushB(/*参数*/){for(int i=0;i<n;i++){/*试探坐标的索引*/if(r==x&&c==y){step++;if(step<min){min=step;}return 0;}/*非出口但可走执行的操作*/}return 0;
}
从当前位置走到出口处,所用步数step加一,比较step和min,记录其最小值,结束当前位置(非出口,是出口前一步)的试探。
在这次递归中,若此时的方向能够一步走到终点,即使剩余尚未试探的方向还可以走甚至能走通,所用步数也会多余此方向,故直接结束本次递归函数减少程序无谓的运算。同时该试探位置为出口,不用检测是否超出边界、是否存在陷阱。
非出口但可走执行的操作如下:
int rushB(/*参数*/){for(int i=0;i<n;i++){/*试探坐标的索引*//*走到出口执行的操作*/if(r>=0&&c>=0&&r<n&&c<m){//超出边界检测if(!map[r][c]){//有无陷阱检测step++;map[R][C] = 1;rushB(map,r,c,step);//进入下一步step--;map[R][C] = 0;}}}return 0;
}
检测试探位置是否超出了边界,若超出则后续无操作,试探下一个方向,若未超出,则进一步判断试探位置是否有陷阱存在,若有陷阱则后续无操作,试探下一个方向,若无陷阱,则:
- 前进到试探位置,步数step加一。
- 在任意后续步骤的试探中不能再走到原来所处的位置,通过将其该位置设置为有陷阱实现。
- 调用rushB()函数,前进到此次试探的位置进行新一轮的试探,传入试探位置坐标索引作为新一轮试探的起始位置。
后续无论是走到死胡同还是走到出口,均会依次退后回到本步,即新调用的rushB()函数结束。回到本步后在试探下一个方向之前,应将新调用rushB()函数前做出的更改复原,此时所处位置恢复为无陷阱状态。
在若干个rushB()函数中,数组map是通用的,而R,C,step是每个rushB()函数都有独立的副本,相互之间无干扰,在进入下一步后仍储存着这一步的信息且不会被更改,所以可以实现退回到上一步的操作,在本步退回后该步占用的存储空间才会被释放。
在主函数中调用第一个rushB()函数,枚举所有路线后,第一个rushB()函数结束,得到了最小步数,将其输出:
int main(){/*数据输入部分*/rushB(map,a,b,0);printf("%d\n",min);
}
完整代码
完整代码如下:
#include<stdio.h>
int n,m,a,b,x,y;
int min=2147483647;
int det[2][4] = {{1,-1,0,0},{0,0,1,1}};
int main(){scanf("%d %d",&n,&m);scanf("%d %d %d %d",&a,&b,&x,&y);a--;b--,x--,y--;int map[n][m];for(int i=0;i<n;i++){for(int j=0;j<m;j++){scanf("%d",&map[i][j]);}}rushB(map,a,b,0);printf("%d\n",min);
}
int rushB(int map[n][m],int R,int C,int step){for(int i=0;i<4;i++){int r=R+det[0][i],c=C+det[1][i];if(r==x&&c==y){step++;if(step<min){min=step;}return 0;}if(r>=0&&c>=0&&r<n&&c<m){if(!map[r][c]){step++;map[R][C] = 1;rushB(map,r,c,step);step--;map[R][C] = 0;}}}return 0;
}
代码分析
计算题目示例的平均用时小于0.008s,代码没有中如题目要求的对n和m取值做出限制,没有对输入数据合法性合理性进行判断,没有设置只有死路时的警告提示。
C:勇敢羊羊不怕困难!2022-2023年度第四届全国大学生算法设计与编程挑战赛(秋季赛)之羊驼相关推荐
- 2022“杭电杯”中国大学生算法设计超级联赛(8)
2022"杭电杯"中国大学生算法设计超级联赛(8) [题目链接](Search Result (hdu.edu.cn)) D Quel'Thalas 题目大意 在二维平面上,[0, ...
- 2022“杭电杯”中国大学生算法设计超级联赛(4)
2022"杭电杯"中国大学生算法设计超级联赛(4) [题目链接](Search Result (hdu.edu.cn)) D Link with Equilateral Trian ...
- 2022“杭电杯”中国大学生算法设计超级联赛 (1) 杭电多校第一场 2 3 4 5 8 12
题目 1002 Dragon slayer 标程 1003 Backpack AC代码 1004 Ball AC代码 1008 Path AC代码 1009 Laser AC代码 1012 Alice ...
- 2022“杭电杯”中国大学生算法设计超级联赛 (2) 杭电多校第二场
题目 1001 Static Query on Tree AC代码 1002 C++ to Python AC代码 1003 Copy AC代码 1005 Slayers Come AC代码 1007 ...
- 2022“杭电杯”中国大学生算法设计超级联赛(2)1003.Copy
样例输入: 1 5 3 1 2 3 4 5 2 4 1 2 4 2 5 样例输出: 6 题意: 有q次操作,有以下两种: 1.选择区间[l,r],复制[l,r]追加到r后,总的数组的大小(n)不变 ...
- 2022“杭电杯”中国大学生算法设计超级联赛(8)补题
1004 Quel'Thalas 题意 在二维平面上,点在坐标在[0,n]的区间内,通过添加无限长的直线可以覆盖这些点,在不覆盖(0,0)的情况下要添加多少根直线. 思路 在两个方向上添加直线,所以 ...
- 2022“杭电杯”中国大学生算法设计超级联赛(8)补题 1011 (持续更新中)
目录 1011 Stormwind(贪心--分割矩形) 1011 Stormwind(贪心–分割矩形) /*题解:想要切割的次数最多,让原矩形的一边尽可能被多次切割,另一边紧跟即可*/ #includ ...
- 2022“杭电杯”中国大学生算法设计超级联赛(1)1003 Backpack个人题解
Backpack 题目描述 有n件物品,他们各自都有体积vi和价值wi,给你一个体积为m的背包,求是否能从这n件物品中取出若干件,使得它们的体积之和恰好为m,所有物品的异或和最大,最大值是多少 分析 ...
- 2022“杭电杯”中国大学生算法设计超级联赛(1)C.Backpack
题目链接:Problem - 7140 样例输入: 1 5 4 2 4 1 6 2 2 2 12 1 14 样例输出: 14 题意: 有n个物品,每个物品体积为v[i],价值为w[i] 求是否存在 ...
最新文章
- 高速缓存的数据结构:拉链散列表
- jquery 只能输入汉字
- Java案例:几种方式拷贝文件的耗时比较
- struct device结构体(2.6.23)
- UVA11532 Simple Adjacency Maximization【位运算】
- hystrix文档翻译之Dashboard
- jeecg框架解决跨域问题
- Android项目实践--《智慧校园》
- NXP IMX6ULL芯片时钟系统全概况
- Unity3D 编辑器功能之MonoBehaviour属性
- .bat批处理(十一):替换字符串中包含百分号%的子串
- python图像处理:核磁共振图像(3D)的缩放
- 网络安全——常见的几种WEB攻击:
- 七个关键心理学(4)沉没成本
- python在大数据处理的应用
- 做web前端开发就是爽!不仅工资高而且没事还能写个游戏玩!真棒
- js获取对象的父元素,子元素,兄弟元素
- jsp+struct标签实现分页(只有jsp代码),内用到迭代标签、if标签、bean
- php自定义词库简单分词,敏感词替换
- 从0开始学习微服务(二)
热门文章
- 突发!继22岁拼多多女员工猝死后,又一悲剧:拼多多员工家中跳楼自杀!公司紧急通告!...
- svn: E155007: 'XXX' is not a working copy
- 腾讯实时音视频SDK[三]:小程序端实现
- vba遍历字符串_VBA7种文档遍历法
- linux 鼠标中键多余字符,取消Linux下的鼠标中键粘贴功能
- 在手机桌面隐藏App的Icon并启动该App
- 非主流伤感QQ空间日志_享受着自己的那份孤独
- adb shell提示:device unauthorized
- Isolation Forest 孤立森林
- 如何建设自己的网站 博客