POJ 1324 Holedox Moving
来源:互联网 发布:淘宝商品条形码怎么填 编辑:程序博客网 时间:2024/06/05 14:42
Name: Holedox Moving
P_ID: POJ 1324
题目链接:http://poj.org/problem?id=1324
题意描述:
n*m(最大20)的迷宫,l长(不超过8)的贪吃蛇,蛇身可弯曲,出口在(1,1),不能走石头所在格子,求蛇身最少移动次数。
题目分析:
题目本身是要考bfs最短路这个很明确,唯一不寻常的是在蛇移动过程中蛇身也在动。刚开始我认为这道题并没有什么特别的地方,于是采用了很普通的一种想法:
正常对头到(1,1)进行bfs,每次状态,我判断头周围的格子,当既不是石头,也不是蛇身的时候,说明这个格子是可以走的,我进行如下三个操作:
1. 蛇身移动一格(依次前移,蛇头新位置入队)
2. 将新的蛇头所在位置vis标记为1
3. 原蛇尾位置标记为空(代表可走)
下面是我的代码:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <stack>#include <queue>#include <set>#include <map>#include <string>#include <cmath>#include <cstdlib>#include <ctime>using namespace std;typedef long long ll;const int MOD = 1e9 + 7;const int MAXN = 1e5 + 3;int n, m, l, b;int num = 0;char maze[25][25];int vis[21][21];const int dir[][2] = {{0,1}, {0,-1}, {1,0}, {-1,0}};struct cell { int x; int y; cell(int a, int b) { x = a; y = b; }};struct node { int x; int y; int step; vector<cell> myBody;};int flag = 0;vector<cell> myBody;bool check(int x, int y){ if(x<1 || x>n || y<1 || y>m) return false; if(maze[x][y]=='L' || maze[x][y]=='X') return false; return true;}void moveWork(int xx, int yy, vector<cell> &a){ for(int i=a.size()-1; i>0; --i) { a[i].x = a[i-1].x; a[i].y = a[i-1].y; } a[0].x = xx; a[0].y = yy;}int bfs(){ node first; first.x = myBody[0].x; first.y = myBody[0].y; first.step = 0; first.myBody = myBody; queue<node> myPath; myPath.push(first); while(!myPath.empty()) { node now = myPath.front(); myPath.pop(); // cout << now.x << "," << now.y << "---" << now.step << endl; if(now.x==1 && now.y==1) return now.step; for(int i=0; i<4; ++i) { int xx = now.x + dir[i][0]; int yy = now.y + dir[i][1]; if(check(xx, yy) && !vis[xx][yy]) { vector<cell> mmBody = now.myBody; moveWork(xx, yy, mmBody); node next; next.x = xx; next.y = yy; next.step = now.step + 1; next.myBody = mmBody; myPath.push(next); vis[xx][yy] = 1; flag = 1; } } int p = now.myBody[l-1].x; int q = now.myBody[l-1].y; maze[p][q] = '.'; flag = 0; } return -1;}int main(){ while(scanf("%d%d%d", &n, &m, &l)) { flag = 0; num++; if(n==0 && m==0 & l==0) break; memset(maze, '.', sizeof(maze)); memset(vis, 0, sizeof(vis)); while(!myBody.empty()) myBody.clear(); for(int i=0; i<l; ++i) { int x; int y; scanf("%d%d", &x, &y); maze[x][y] = 'L'; myBody.push_back(cell(x,y)); } scanf("%d", &b); for(int i=0; i<b; ++i) { int x; int y; scanf("%d%d", &x, &y); maze[x][y] = 'X'; } int ans; ans = bfs(); if(ans==-1) printf("Case %d: -1\n", num); else printf("Case %d: %d\n", num, ans); } return 0;}
交上去的下场是:
Wrong Answer
为什么呢?
刚刚我的代码中,vis所记录的是一个二维数组,只标记了迷宫本身,也就是说我保证蛇头不走重复的路,但是,事实上这是不对的。因为有一些情况下蛇是需要走一些路途把身体甩过去,然后回过头才可能有路能出到出口去,这种情况下蛇头就必然会有重复的迷宫位置需要去走。
此外,可能甚至有一些情况下:蛇通过重复走同一个位置,把蛇身甩过去,比直接不走重复位置到出口所需步数更加少。
这个问题我居然一直没有想到,直到看了http://blog.csdn.net/u013480600/article/details/25336473
的题解才发现这个问题。
因此,为了解决这个问题,我们的vis数组就不能只有二维了。而是需要第三维,用来存储蛇身的弯曲状态。
[参考AC代码]
/** * Name: Gluttonous Snake * P_ID: POJ_1324 * date: 2016-04-27 * note: bit operation + status memory * */#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <stack>#include <queue>#include <set>#include <map>#include <string>#include <cmath>#include <cstdlib>#include <ctime>using namespace std;typedef long long ll;const int MOD = 1e9 + 7;const int MAXN = 1e5 + 3;int n, m, l, b;int num = 0;char maze[25][25];int vis[21][21][1<<14];const int dir[][2] = {{1,0}, {0,-1}, {-1,0}, {0,1}};int d[10];struct cell { int x; int y; cell(int a, int b) { x = a; y = b; }};struct node { int x; int y; int step; int status; node(int a, int b, int c, int d) { x = a; y = b; step = c; status = d; }};int flag = 0;bool check(int x, int y, node temp){ if(x<1 || x>n || y<1 || y>m) return false; if(maze[x][y]=='X') return false; for(int i=l-1; i>=1; --i) { d[i] = temp.status&3; temp.status>>=2; } int xx = temp.x, yy = temp.y; for(int i=1; i<l; ++i) { xx+=dir[d[i]][0]; yy+=dir[d[i]][1]; if(xx==x && yy==y) return false; } return true;}int bfs(node &start){ vis[start.x][start.y][start.status] = num; queue<node> myPath; myPath.push(start); while(!myPath.empty()) { node now = myPath.front(); myPath.pop(); // cout << now.x << "," << now.y << "---" << now.step << endl; if(now.x==1 && now.y==1) return now.step; int nx = now.x; int ny = now.y; int ns = now.status; int np = now.step; for(int i=0; i<4; ++i) { int xx = nx + dir[i][0]; int yy = ny + dir[i][1]; if(xx==1 && yy==1) return np+1; int nst = (ns>>2) + (((i+2)%4)<<(2*(l-2))); if(check(xx, yy, now) && vis[xx][yy][nst]!=num) { myPath.push(node(xx, yy, np+1, nst)); vis[xx][yy][nst] = num; } } } return -1;}int main(){ while(scanf("%d%d%d", &n, &m, &l)) { flag = 0; num++; if(n==0 && m==0 & l==0) break; memset(maze, '.', sizeof(maze)); int x, y; scanf("%d%d", &x, &y); node first(x,y,0,0); int nx, ny; for(int i=1; i<l; ++i) { scanf("%d%d", &nx, &ny); for(int j=0; j<4; ++j) { if(x+dir[j][0]==nx && y+dir[j][1]==ny) { first.status = (first.status<<2) + j; break; } } x = nx; y = ny; } scanf("%d", &b); for(int i=0; i<b; ++i) { int x; int y; scanf("%d%d", &x, &y); maze[x][y] = 'X'; } int ans; ans = bfs(first); if(ans==-1) printf("Case %d: -1\n", num); else printf("Case %d: %d\n", num, ans); } return 0;}
- poj 1324 Holedox Moving
- POJ-1324-Holedox Moving
- poj 1324 Holedox Moving
- POJ 1324 Holedox Moving
- POJ - 1324 Holedox Moving
- POJ-1324 Holedox Moving
- poj 1324 Holedox Moving
- POJ 1324 Holedox Moving
- POJ-1324 Holedox Moving
- Poj 1324 Holedox Moving (A*)
- POJ 1324 Holedox Moving 搜索
- POJ-1324-Holedox Moving(BFS)
- POJ 1324 Holedox Moving 贪食蛇
- POJ 1324 Holedox Moving(bfs + hash)
- POJ 1324 Holedox Moving (BFS+剪枝)
- POJ 1324 Holedox Moving(状态压缩BFS)
- POJ 1324 Holedox Moving(图论:BFS)
- POJ 1324 Holedox Moving 位运算+BFS
- 特征选择与特征学习
- Linux两个函数mbstowcs() 与wcstombs()
- Python ImportError:No module named的问题
- 面向对象
- 类型转换错误java.math.BigDecimal cannot be cast to java.lang.String
- POJ 1324 Holedox Moving
- Servlet和JSP中取参
- java反射中getDeclaredField和getField的区别
- excel----随机选取一行中的某一个单元格
- git 高级使用
- Android手势密码实现方案
- IMP
- [Excel]按照合约匹配交易所
- IE11 F12工具报错