poj1324 - Holedox Moving(BFS+状态压缩)
2017-03-11 00:15
495 查看
题目链接:点击打开链接
题意:
一只长度为L的蛇要到达左上角的出口,问最短步数。
思路:
在最基本的bfs里,我们要记录每个状态是否已经访问过,在基础题里通常只是一个点,设置一个vis[x][y]=true就ok了。
在这题中,我们要把蛇身整体在某一位置看成一个状态,要表达L长度的身体,需要的空间很大,将是400^8;
我们把蛇头单独抽取出来,作为vis数组的前两维。第三维,我们将蛇的身体压缩到一个数字中,蛇的身体的每一节,相对于前面一节的位置,只有4种可能,即前后左右4种可能,蛇身最长为7,那么我们用两个2进制位(或者说4进制)表示每一节身体相对前一节的位置,然后左移两位,之后重复操作整个蛇身。那么压缩后,占用的空间为4^7=16384。
要注意的一点是,头不允许到达刚才尾巴的位置,如第一图中B1不能马上到达B4的位置。
失误:
将bfs出口放在了循环里,导致遗漏情况。
PS:
太慢了..
代码:
题意:
一只长度为L的蛇要到达左上角的出口,问最短步数。
思路:
在最基本的bfs里,我们要记录每个状态是否已经访问过,在基础题里通常只是一个点,设置一个vis[x][y]=true就ok了。
在这题中,我们要把蛇身整体在某一位置看成一个状态,要表达L长度的身体,需要的空间很大,将是400^8;
我们把蛇头单独抽取出来,作为vis数组的前两维。第三维,我们将蛇的身体压缩到一个数字中,蛇的身体的每一节,相对于前面一节的位置,只有4种可能,即前后左右4种可能,蛇身最长为7,那么我们用两个2进制位(或者说4进制)表示每一节身体相对前一节的位置,然后左移两位,之后重复操作整个蛇身。那么压缩后,占用的空间为4^7=16384。
要注意的一点是,头不允许到达刚才尾巴的位置,如第一图中B1不能马上到达B4的位置。
失误:
将bfs出口放在了循环里,导致遗漏情况。
PS:
Status | Accepted |
---|---|
Time | 4688ms |
Memory | 10944kB |
Length | 2424 |
Lang | G++ |
Submitted | 2017-03-10 14:51:52 |
Shared | |
RemoteRunId | 16704097 |
代码:
#include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; const int dx[4] = {0, 0, 1, -1}; const int dy[4] = {1, -1, 0, 0}; const int MAXN = 20+2; int n, m, l; bool tu[MAXN][MAXN]; bool vis[MAXN][MAXN][1<<14]; struct Tuple { int x, y; }; struct Node { int step; Tuple snake[8]; }; Node st; inline bool judge(int x, int y, int z){ return (0<=x&&x<n && 0<=y&&y<m && !tu[x][y] && !vis[x][y][z]); } int getDirect(int x, int y, int tx, int ty){ if(x==tx){ if(y==ty-1) return 0; //up else return 1; //down } else{ if(x-1==tx) return 2; //left else return 3; //right } } int cal(Node &t){ int ret = 0; for(int i=1; i<l; ++i){ ret = (ret<<2) + getDirect(t.snake[i-1].x, t.snake[i-1].y, t.snake[i].x, t.snake[i].y); } return ret; } void SnakeMove(Node &now, Node &pre){ for(int i=1; i<l; ++i){ now.snake[i].x = pre.snake[i-1].x; now.snake[i].y = pre.snake[i-1].y; } ++now.step; } bool judgeBody(Node &now){ for(int i=1; i<l; ++i){ if(now.snake[i].x==now.snake[0].x && now.snake[i].y==now.snake[0].y) return true; } return false; } int bfs(){ queue<Node> q; st.step = 0; q.push(st); vis[st.snake[0].x][st.snake[0].y][cal(st)] = true; while(!q.empty()){ Node temp = q.front(); q.pop(); for(int i=0; i<4; ++i){ Node now = temp; now.snake[0].x += dx[i]; now.snake[0].y += dy[i]; int x = now.snake[0].x; int y = now.snake[0].y; if(x<0||y<0||x>=n||y>=m||tu[x][y]) continue; //判断蛇头是否在边界内以及是否为石头 if(x==now.snake[l-1].x&&y==now.snake[l-1].y) continue; //特殊情况不允许头追尾 SnakeMove(now, temp); //move and step+1 if(judgeBody(now)) continue; //判断蛇头是否和身体相撞 int z = cal(now); if(vis[x][y][z]) continue; //判断是否访问过 if(x==0&&y==0) return now.step; q.push(now); vis[x][y][z] = true; } } return -1; } int main(){ int x, y, cas=0; while(scanf("%d%d%d", &n, &m, &l)!=EOF){ if(n==0&&m==0&&l==0) break; memset(tu, 0, sizeof(tu)); memset(vis, 0, sizeof(vis)); for(int i=0; i<l; ++i){ scanf("%d%d", &x, &y); st.snake[i].x = x-1; st.snake[i].y = y-1; } int stone; scanf("%d", &stone); for(int i=0; i<stone; ++i){ scanf("%d%d", &x, &y); tu[x-1][y-1] = true; } if(st.snake[0].x==0 && st.snake[0].y==0) printf("Case %d: %d\n", ++cas, 0); else printf("Case %d: %d\n", ++cas, bfs()); } return 0; }
相关文章推荐
- Holedox Moving----POJ_1324----BFS+状态压缩
- poj 1324 Holedox Moving(bfs+状态压缩)
- POJ-1324:Holedox Moving(BFS+状态压缩+蛇蛇历险记)
- 状态压缩+BFS POJ - 1324 Holedox Moving
- poj 1324(BFS+状态压缩)
- POJ 1324 BFS+状态压缩
- poj1324-Holedox Moving-状态压缩+BFS
- POJ 1324 Holedox Moving(状态压缩BFS)
- POJ 1324 Holedox Moving(A*+状态压缩)
- POJ 1324 BFS+状态压缩 蛇走迷宫
- POJ 1324 Holedox Moving 状态压缩+A* -
- [poj1324]状态压缩+BFS
- POJ 1324(BFS + 状态压缩)
- uva 1601 poj 3523 Morning after holloween 万圣节后的早晨 (经典搜索,双向bfs+预处理优化+状态压缩位运算)
- POJ 1753 Flip Game(bfs+状态压缩+位运算)
- POJ 1753 Flip Game(BFS+状态压缩)
- pku 1324 Holedox Moving 冬眠蛇 bfs+状态保存+强剪枝
- poj 1324 状态压缩+bfs
- POJ - 1137:The New Villa(bfs+状态压缩)
- POJ 1324Holedox Moving (状态BFS)