目录

题目分析

程序设计

总体流程

信息输入

递归函数

完整代码

代码分析

题目分析

问题描述如图:

利用函数迭代,找出能走到出口的每一条路,取路径最短的路线。

程序设计

总体流程

  • 输入相应的地图信息。
  • 从初始位置开始,向四个方向试探(不超出边界)。
  • 若试探位置没有陷阱,以该位置作为新的起始点重复流程(应该把来路设置为有陷阱避免反复横跳)。
  • 若试探位置有陷阱,换个方向进行试探。
  • 位于死胡同时(各个方向均无路可走),返回上一步所在位置,试探该位置的其他方向。
  • 走到终点时,记录所用步数,与历史最少步数比较,保留最小值。退后若干步试探新的路线。
  • 将所有走法试探一遍后,结束试探,输出最小步数。

信息输入

为方便递归函数调用,将地图基本信息声明为全局变量:

#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年度第四届全国大学生算法设计与编程挑战赛(秋季赛)之羊驼相关推荐

  1. 2022“杭电杯”中国大学生算法设计超级联赛(8)

    2022"杭电杯"中国大学生算法设计超级联赛(8) [题目链接](Search Result (hdu.edu.cn)) D Quel'Thalas 题目大意 在二维平面上,[0, ...

  2. 2022“杭电杯”中国大学生算法设计超级联赛(4)

    2022"杭电杯"中国大学生算法设计超级联赛(4) [题目链接](Search Result (hdu.edu.cn)) D Link with Equilateral Trian ...

  3. 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 ...

  4. 2022“杭电杯”中国大学生算法设计超级联赛 (2) 杭电多校第二场

    题目 1001 Static Query on Tree AC代码 1002 C++ to Python AC代码 1003 Copy AC代码 1005 Slayers Come AC代码 1007 ...

  5. 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)不变 ...

  6. 2022“杭电杯”中国大学生算法设计超级联赛(8)补题

    1004  Quel'Thalas 题意 在二维平面上,点在坐标在[0,n]的区间内,通过添加无限长的直线可以覆盖这些点,在不覆盖(0,0)的情况下要添加多少根直线. 思路 在两个方向上添加直线,所以 ...

  7. 2022“杭电杯”中国大学生算法设计超级联赛(8)补题 1011 (持续更新中)

    目录 1011 Stormwind(贪心--分割矩形) 1011 Stormwind(贪心–分割矩形) /*题解:想要切割的次数最多,让原矩形的一边尽可能被多次切割,另一边紧跟即可*/ #includ ...

  8. 2022“杭电杯”中国大学生算法设计超级联赛(1)1003 Backpack个人题解

    Backpack 题目描述 有n件物品,他们各自都有体积vi和价值wi,给你一个体积为m的背包,求是否能从这n件物品中取出若干件,使得它们的体积之和恰好为m,所有物品的异或和最大,最大值是多少 分析 ...

  9. 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] 求是否存在 ...

最新文章

  1. 高速缓存的数据结构:拉链散列表
  2. jquery 只能输入汉字
  3. Java案例:几种方式拷贝文件的耗时比较
  4. struct device结构体(2.6.23)
  5. UVA11532 Simple Adjacency Maximization【位运算】
  6. hystrix文档翻译之Dashboard
  7. jeecg框架解决跨域问题
  8. Android项目实践--《智慧校园》
  9. NXP IMX6ULL芯片时钟系统全概况
  10. Unity3D 编辑器功能之MonoBehaviour属性
  11. .bat批处理(十一):替换字符串中包含百分号%的子串
  12. python图像处理:核磁共振图像(3D)的缩放
  13. 网络安全——常见的几种WEB攻击:
  14. 七个关键心理学(4)沉没成本
  15. python在大数据处理的应用
  16. 做web前端开发就是爽!不仅工资高而且没事还能写个游戏玩!真棒
  17. js获取对象的父元素,子元素,兄弟元素
  18. jsp+struct标签实现分页(只有jsp代码),内用到迭代标签、if标签、bean
  19. php自定义词库简单分词,敏感词替换
  20. 从0开始学习微服务(二)

热门文章

  1. 突发!继22岁拼多多女员工猝死后,又一悲剧:拼多多员工家中跳楼自杀!公司紧急通告!...
  2. svn: E155007: 'XXX' is not a working copy
  3. 腾讯实时音视频SDK[三]:小程序端实现
  4. vba遍历字符串_VBA7种文档遍历法
  5. linux 鼠标中键多余字符,取消Linux下的鼠标中键粘贴功能
  6. 在手机桌面隐藏App的Icon并启动该App
  7. 非主流伤感QQ空间日志_享受着自己的那份孤独
  8. adb shell提示:device unauthorized
  9. Isolation Forest 孤立森林
  10. 如何建设自己的网站 博客