sdutoj 1157 小鼠迷宫问题
2013-10-03 18:27
387 查看
题目链接: sdutoj 1157 小鼠迷宫问题
/* * 作者 仪冰 * QQ 974817955 * 题目 sdutoj 1157 小鼠迷宫问题 【题目描述】 小鼠a与小鼠b身处一个m×n的迷宫中,如图所示。每一个方格表示迷宫中的一个房间。这m×n个房间中有一些房间是封闭的,不允许任何人进入。在迷宫中任何位置均可沿上,下,左,右4个方向进入未封闭的房间。小鼠a位于迷宫的(p,q)方格中,它必须找出一条通向小鼠b所在的(r,s)方格的路。请帮助小鼠a找出所有通向小鼠b的最短道路。 【输入】 本题有多组输入数据,你必须处理到EOF为止。 每组数据的第一行有3个正整数n,m,k,分别表示迷宫的行数,列数和封闭的房间数。 接下来的k行中,每行2个正整数,表示被封闭的房间所在的行号和列号。 最后的2行,每行也有2个正整数,分别表示小鼠a所处的方格(p,q)和小鼠b所处的方格(r,s)。 【输出】 对于每组数据,将计算出的小鼠a通向小鼠b的最短路长度和有多少条不同的最短路输出。 每组数据输出两行,第一行是最短路长度;第2行是不同的最短路数。 每组输出之间没有空行。 如果小鼠a无法通向小鼠b则输出“No Solution!”。 【示例输入】 8 8 3 3 3 4 5 6 6 2 1 7 7 【示例输出】 11 96 【思路】 用BFS求最短路径长度;用DFS求最短路径条数。 DFS时,用到奇偶性剪枝,剪枝很重要。 */ #include <iostream> #include <string> #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <stack> using namespace std; const int SIZE = 102; //边界数组,四个方向,按照下、右、上、左的顺序 int coordinate[4][2] = {1,0, 0,1, -1,0, 0,-1}; int mazeBfs[SIZE][SIZE]; //广搜用的迷宫 int mazeDfs[SIZE][SIZE]; //深搜用的迷宫 int oddEven[SIZE][SIZE]; //奇偶剪枝状态数组 int n; //迷宫行数 int m; //迷宫列数 int k; //封闭房间数 int kr, kl; //每个封闭房间的行号和列号 int p, q; //小鼠a的行号和列号 int r, s; //小鼠b的行号和列号 int ShortestPathLength; //最短路径的长度 int ShortestPahtNumber; //最短路径的条数 //广搜求最短路径长度 //int BFS(int p, int q, int r, int s, int len, int n, int m); int BFS(); //深搜求最短路径条数 //void DFS(int x, int y, int r, int s, int len, int n, int m, int shortlength); void DFS(int x, int y, int 4000 len); int main() { while (scanf("%d%d%d", &n, &m, &k) != EOF) { memset(mazeBfs, 0, sizeof(mazeBfs)); //初始化迷宫 memset(mazeDfs, 0, sizeof(mazeDfs)); //奇偶剪枝数组初始化 for (int i=0; i<=n; i++) { if (i%2 == 1) { for (int j=0; j<=m; j++) { if (j%2 == 1) { oddEven[i][j] = 1; } else { oddEven[i][j] = 0; } } } else { for (int j=0; j<=m; j++) { if (j%2 == 1) { oddEven[i][j] = 0; } else { oddEven[i][j] = 1; } } } } for (int i=1; i<=k; i++) { scanf("%d%d", &kr, &kl); //输入封闭房间的坐标 //存入迷宫中,迷宫中,1代表封闭房间,0代表可以走 mazeBfs[kr][kl] = 1; mazeDfs[kr][kl] = 1; } scanf("%d%d", &p, &q); //小鼠a的坐标 scanf("%d%d", &r, &s); //小鼠b的坐标 //求最短路径长度 ShortestPathLength = BFS(); if (ShortestPathLength == -1) //没路可走时 { printf("No Solution!\n"); continue; } //求最短路径条数 ShortestPahtNumber = 0; DFS(p, q, 0); //输出结果 printf("%d\n%d\n", ShortestPathLength, ShortestPahtNumber); } return 0; } int BFS() { queue<int> qx; //存横坐标的队列 queue<int> qy; //存纵坐标的队列 queue<int> qlen; //存长度的队列 int xa, ya; //当前节点坐标 int length; //到达当前节点长度 qx.push(p); qy.push(q); qlen.push(0); mazeBfs[p][q] = 1; while (!qx.empty()) { if ((qx.front()==r) && (qy.front()==s)) //判断是否到达小鼠b { return qlen.front(); } //临时保存队头值 int xx, yy ,ll; xx = qx.front(); yy = qy.front(); ll = qlen.front(); //保存完之后,出队 qx.pop(); qy.pop(); qlen.pop(); for (int i=0; i<4; i++) { //算第i方向上的新值 xa = xx + coordinate[i][0]; ya = yy + coordinate[i][1]; length = ll; //新的点在迷宫内,且没有走过 if ((xa>=1) && (xa<=n) && (ya>=1) && (ya<=m) && (mazeBfs[xa][ya]==0)) { //入队 qx.push(xa); qy.push(ya); length += 1; qlen.push(length); //标记新点 mazeBfs[xa][ya] = 1; } } } return -1; //如果没有路,返回0 } void DFS(int x, int y, int len) { if ((x==r) && (y==s) && (len==ShortestPathLength)) //找到一条最短路径 { ShortestPahtNumber++; return ; } //一般剪枝 int theoryShortestLength; //当前节点到终点的理论最小值 theoryShortestLength = (abs(x-r)) + (abs(y-s)); if ((len+theoryShortestLength) > ShortestPathLength) //当前长度+理论最小值>最短路径长度 { return ; } //奇偶剪枝 if ((ShortestPathLength-len)%2 != ((abs(oddEven[x][y]-oddEven[r][s])) % 2)) { return ; } for (int i=0; i<4; i++) { int xx, yy; xx = x + coordinate[i][0]; yy = y + coordinate[i][1]; if ((xx>=1) && (xx<=n) && (yy>=1) && (yy<=m) && (mazeDfs[xx][yy]==0)) { mazeDfs[xx][yy] = 1; DFS(xx, yy, len+1); //回溯 mazeDfs[xx][yy] = 0; } } }
相关文章推荐
- SDUT 1157-小鼠迷宫问题(BFS&DFS)
- FZU1205/SDUT1157_小鼠迷宫问题(DFS+BFS)
- 小鼠迷宫问题【sdut1157】【dfs,bfs综合题目】
- 小鼠迷宫问题---1157
- SDUT 1157-小鼠迷宫问题(BFS&DFS)
- 小鼠迷宫问题 SDUT1157 ACM算法设计
- 小鼠迷宫问题uva1157
- 小鼠迷宫问题
- 小鼠迷宫问题
- FZU 1205 小鼠迷宫问题
- fjnu 1354 小鼠迷宫问题
- fuz 1205(小鼠迷宫问题)
- FZU 1205 小鼠迷宫问题 <BFS+DFS>
- 第一题:小鼠迷宫问题(方法:广搜)
- FZU - 1205 小鼠迷宫问题 (bfs+dfs)
- 小鼠迷宫问题
- FOJ1205 小鼠迷宫问题 (BFD+递推)
- 小鼠迷宫问题
- nku1215: 小鼠迷宫问题
- FOJ 1205 小鼠迷宫问题【BFS+dfs回溯查找路径】