POJ 3083 Children of the Candy Corn(走迷宫)
2015-12-25 16:31
477 查看
题目链接:POJ 3083
题意:
给一个迷宫,‘#’代表墙,'.'代表可行,’S‘代表入口,’E‘代表出口。分别求出:
①按左、上、右、下顺序前行从入口到出口的步数。
②按右、上、左、下顺序前行从入口到出口的步数。
③从入口到出口的最短步数。
入口在边上但不在拐角处。入口和出口也各算一步。
分析:
最短路径直接用BFS求解。
先分析第一种要求,即左上右下的顺序,第二种与之类似。
入口在不同的边上下一步走的方向下标变化是不一样的。
①当srow=0时,顺序是: { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 };【入口在最上面一条边】
②当srow=h-1时,顺序是:{ 0,-1 },{ -1,0 },{ 0,1 },{ 1,0 };【入口在最下面一条边】
③当scol=0时,顺序是: { -1,0 },{ 0,1},{ 1,0 },{ 0,-1 };【入口在最左面一条边】
④当scol=w-1时,顺序是: { 1,0 },{ 0,-1 }, { -1,0 },{ 0,1}。【入口在最右边一条边】
仔细观察可以发现:①和②其实是同一个序列【相对顺序是一样的】,③和④是同一个序列。所以可以分两类方向逐个查找,沿右上左下顺序前行也是同样的道理。
在方向上还有一点需要考虑。拿测试一来说,移动的顺序是:
(7,1)->(6,1)->(5,1)->(4,1)->(3,1)->(2,1)->(1,1)->(1,2)->(1,3)->......
注意:(1,1)之前的搜索方向顺序是:{ 0,-1 },{ -1,0 },{ 0,1 },{ 1,0 };转向后,
从(1,2)开始搜索方向顺序变为:{ -1,0 },{ 0,1 },{ 1,0 },{ 0,-1 }。通过多写几组下标变化对比可以发现规律:用dfs传递的方向下标是:(当前方向下标+3)%4
难点:
搜索方向的确定
dfs传递的参数:下一搜索点,下一次开始搜索方向下标,移动步数,搜索方向数组
找到出口时返回的是step+1
在dfs函数里有两个return:找到出口和return dfs(...)。
参考链接:POJ 3083
题意:
给一个迷宫,‘#’代表墙,'.'代表可行,’S‘代表入口,’E‘代表出口。分别求出:
①按左、上、右、下顺序前行从入口到出口的步数。
②按右、上、左、下顺序前行从入口到出口的步数。
③从入口到出口的最短步数。
入口在边上但不在拐角处。入口和出口也各算一步。
分析:
最短路径直接用BFS求解。
先分析第一种要求,即左上右下的顺序,第二种与之类似。
入口在不同的边上下一步走的方向下标变化是不一样的。
①当srow=0时,顺序是: { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 };【入口在最上面一条边】
②当srow=h-1时,顺序是:{ 0,-1 },{ -1,0 },{ 0,1 },{ 1,0 };【入口在最下面一条边】
③当scol=0时,顺序是: { -1,0 },{ 0,1},{ 1,0 },{ 0,-1 };【入口在最左面一条边】
④当scol=w-1时,顺序是: { 1,0 },{ 0,-1 }, { -1,0 },{ 0,1}。【入口在最右边一条边】
仔细观察可以发现:①和②其实是同一个序列【相对顺序是一样的】,③和④是同一个序列。所以可以分两类方向逐个查找,沿右上左下顺序前行也是同样的道理。
在方向上还有一点需要考虑。拿测试一来说,移动的顺序是:
(7,1)->(6,1)->(5,1)->(4,1)->(3,1)->(2,1)->(1,1)->(1,2)->(1,3)->......
注意:(1,1)之前的搜索方向顺序是:{ 0,-1 },{ -1,0 },{ 0,1 },{ 1,0 };转向后,
从(1,2)开始搜索方向顺序变为:{ -1,0 },{ 0,1 },{ 1,0 },{ 0,-1 }。通过多写几组下标变化对比可以发现规律:用dfs传递的方向下标是:(当前方向下标+3)%4
难点:
搜索方向的确定
dfs传递的参数:下一搜索点,下一次开始搜索方向下标,移动步数,搜索方向数组
找到出口时返回的是step+1
在dfs函数里有两个return:找到出口和return dfs(...)。
参考链接:POJ 3083
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <queue> using namespace std; const int maxn = 41; char s[maxn]; int vis[maxn][maxn],a[maxn][maxn]; int n, w, h, x, y, newx, newy, t; int srow, scol, erow, ecol, startindex; //srow,scol,erow,ecol分别是起点终点下标,startindex是开始探索方向下标 int ansbfs, ansleft, ansright; int flag = 0; int dirleft1[4][2] = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } }; int dirleft2[4][2] = { { -1,0 },{ 0,1},{ 1,0 },{ 0,-1 } }; int dirright1[4][2] = { { 0,-1 },{ 1,0 },{ 0,1 },{ -1,0 } }; int dirright2[4][2] = { { 1,0 },{ 0,1 },{ -1,0 },{ 0,-1 } }; int dfs(int x, int y, int k, int step, int dir[4][2]) { for (int i = 0;i < 4;i++) { t = (k + i) % 4;//这样避免了方向下标越界 newx = x + dir[t][0]; newy = y + dir[t][1]; if (newx == erow&&newy == ecol) return step+1;//+1是因为终点也算一个 if(newx < 0 || newy < 0 || newx >= h || newy >= w || a[newx][newy]||(newx==srow&&newy==scol)) continue; //下标不能越界;遇墙跳过;不能再去起点 return dfs(newx, newy, (t+3)%4, step + 1, dir); //因为下一次再从左/右边开始时可能已经‘转向’了,例如测试一里从(1,1)到(1,2),所以这里要传递(t+3)%4,而不是k } } int dirbfs[4][2] = { {1,0},{-1,0},{0,1},{0,-1} }; struct Node { int a; int b; int step; }cur,nextnode; int bfs() { queue<Node> q; cur.a = srow; cur.b = scol; cur.step = 1; vis[cur.a][cur.b] = 1; q.push(cur); while (!q.empty()) { cur = q.front(); q.pop(); for (int i = 0;i < 4;i++) { x = cur.a + dirbfs[i][0]; y = cur.b + dirbfs[i][1]; if (x < 0 || y < 0 || x >= h || y >= w || vis[x][y] || a[x][y]) continue; nextnode.a = x; nextnode.b = y; nextnode.step = cur.step + 1; vis[x][y] = 1; if (x == erow&&y == ecol) return cur.step+1; q.push(nextnode); } } } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif cin >> n; while (n--) { cin >> w >> h; for (int i = 0;i < h;i++) { cin >> s; for (int j = 0;j < w;j++) { if (s[j] == '#') a[i][j] = 1;//a[i][j]=1代表墙 else if (s[j] == '.') a[i][j] = 0; else if (s[j] == 'S') { a[i][j] = 0; srow = i; scol = j; } else if (s[j] == 'E') { a[i][j] = 0; erow = i; ecol = j; } } } ansbfs = ansleft = ansright = 0; if (srow == 0 || srow == h - 1) { if (srow == 0) startindex = 0; else startindex = 2; ansleft = dfs(srow, scol, startindex, 1, dirleft1); ansright = dfs(srow, scol, startindex, 1, dirright1); } else if(scol==0||scol==w-1) { if (scol == 0) startindex = 0; else startindex = 2; ansleft = dfs(srow, scol, startindex, 1, dirleft2); ansright = dfs(srow, scol, startindex, 1, dirright2); } memset(vis, 0, sizeof(vis)); ansbfs = bfs(); cout << ansleft<<" "<<ansright<<" "<<ansbfs << endl; } return 0; }
相关文章推荐
- Android Studio系列教程(一)
- iOS开发-NSDate获取当前时区时间
- ArcGIS API for JavaScript 学习之 identifyTask
- Android EditText输入光标居于开头最开始位置
- git 远程提交步骤
- 【Linux】线程并发拷贝程序
- 对不起,您安装的不是正版应用,安装程序无法继续执行
- 一个局部钩子实现
- 实现类似rsync中regex正则表达式
- 【HTTP】Fiddler(三)- Fiddler命令行和HTTP断点调试
- Android Studio基础之编译JNI(七)-学习篇
- CSS3-学习记录三(选择器)
- java的rsa加密解密
- 代理模式
- 大表进行delete性能优化
- iOS中KVC和KVO有哪些用法?
- IOS 多媒体加载 加载音频 AVAudioPlayer
- HBase应用开发回顾与总结系列之四:HBase配置管理类接口设计
- urlcode的理解
- 使用burpsuite_pro_v1.6破解版暴力破解实例