hdu 1401 (双广)
2014-10-26 19:09
120 查看
题意: 在一个8*8的棋盘里有4个棋子,给你这4个棋子的初状态和末状态,问你能否在8步内由初状态转换到末状态,每一步可移动一个棋子到(上下左右)相邻的空格子里,若相邻格子已有棋子,可跳过该棋子,但只可跳过一个棋子,若跳过后仍有棋子,则该方向不可走。
分析:红果果的搜索题,但别看只走8步感觉状态挺少的,细算一下有(4*4)^8=2^32个状态!!再加上初,末状态已知,因此用双向广搜效率要高些,可把状态减少到2*(4*4)^4=2^17,减少的可不是一点半点。
双向广搜是指从头,尾开始搜索,若搜索的过程中两者出现了交叉,则说明能实现状态转换。这里为了方便,我先搜索从起点出发的4步,并将搜索结果标记起来,再从终点开始搜索,若发现前面标记过了的状态,则说明状态可达。
对于状态的储存用了二进制压缩,由于坐标都是从0到7,用三位二进制位就可以表示,8个坐标则总共是24个二进制位,一个int型就可以储存一个状态了。
最后还有注意的一点是,在储存状态时一定要先对坐标排序,以免出现重复,比如 (2,3),(2,4),(5,6),(5,7)与(2,4),(5,6),(5,7),(2,3)虽然顺序不同,但都是同一个状态。
代码:
分析:红果果的搜索题,但别看只走8步感觉状态挺少的,细算一下有(4*4)^8=2^32个状态!!再加上初,末状态已知,因此用双向广搜效率要高些,可把状态减少到2*(4*4)^4=2^17,减少的可不是一点半点。
双向广搜是指从头,尾开始搜索,若搜索的过程中两者出现了交叉,则说明能实现状态转换。这里为了方便,我先搜索从起点出发的4步,并将搜索结果标记起来,再从终点开始搜索,若发现前面标记过了的状态,则说明状态可达。
对于状态的储存用了二进制压缩,由于坐标都是从0到7,用三位二进制位就可以表示,8个坐标则总共是24个二进制位,一个int型就可以储存一个状态了。
最后还有注意的一点是,在储存状态时一定要先对坐标排序,以免出现重复,比如 (2,3),(2,4),(5,6),(5,7)与(2,4),(5,6),(5,7),(2,3)虽然顺序不同,但都是同一个状态。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<cstdlib> #include<cmath> #include<algorithm> #include<queue> #include<stack> #include<set> #include<map> using namespace std; const int N=10; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; map<int,int> m; struct node { int x,y; bool check() { if (x>=0 && x<8 && y>=0 && y<8) return true; else return false; } }; typedef struct State { node pos[4]; int step; }state; bool cmp(node a,node b) { return a.x!=b.x?a.x<b.x:a.y<b.y; } int set_hash(node *a) { int t=0; sort(a,a+4,cmp); for (int i=0;i<4;i++) { t|=(a[i].x<<(6*i)); t|=(a[i].y<<(6*i+3)); } return t; //printf("%o\n",t); } bool judge(int x,int y,node *a,int v) { for (int k=0;k<4;k++) if (k!=v) { if (a[k].x==x && a[k].y==y) return false; } return true; } bool bfs(int kind,state a) { int i,j; int t=set_hash(a.pos); if (kind==2){ if (m[t]==1) return true; } m[t]=kind; queue<state> q; q.push(a); while(!q.empty()) { state u=q.front(); q.pop(); if (u.step>=4) continue; for (i=0;i<4;i++) for (j=0;j<4;j++) { state v=u; v.step++; v.pos[i].x+=dx[j]; v.pos[i].y+=dy[j]; if (!v.pos[i].check()) continue; if (judge(v.pos[i].x, v.pos[i].y, u.pos, i)){ t=set_hash(v.pos); if (kind==1) { if (m[t]!=1) { m[t]=1; q.push(v); } } else { if (m[t]==1) return true; else if (m[t]!=2) { m[t]=2; q.push(v); } } } else { v.pos[i].x+=dx[j]; v.pos[i].y+=dy[j]; if (!v.pos[i].check() || !judge(v.pos[i].x, v.pos[i].y, u.pos, i)) continue; t=set_hash(v.pos); if (kind==1) { if (m[t]!=1) { m[t]=1; q.push(v); } } else { if (m[t]==1) return true; else if (m[t]!=2) { m[t]=2; q.push(v); } } } } } return false; } int main() { int i,j,k; state s,e; while(cin>>s.pos[0].x>>s.pos[0].y) { s.pos[0].x--; s.pos[0].y--; for (i=1;i<4;i++){ cin>>s.pos[i].x>>s.pos[i].y; s.pos[i].x--; s.pos[i].y--; } for (i=0;i<4;i++){ cin>>e.pos[i].x>>e.pos[i].y; e.pos[i].x--; e.pos[i].y--; } s.step=0; e.step=0; bfs(1,s); printf("%s\n",bfs(2,e)?"YES":"NO"); m.clear(); } }
相关文章推荐
- hdu 1401/poj 1198 Solitaire(BFS,剪枝)
- HDU 1401 Solitaire(双向BFS)
- hdu 1401 Solitaire (双向广搜)
- hdu 1401
- HDU 1401 Solitaire (双向广搜)
- POJ 1198/HDU 1401
- HDU_1401——同步双向BFS,八进制位运算压缩,map存放hash
- HDU 1401 Solitaire (双向搜索)
- hdu 1401(单广各种卡的搜索题||双广秒速)
- HDU 1401 Solitaire(双向广度优先搜索)
- HDU 1401 Solitaire(双向搜索)
- hdu 1401
- hdu 1401 Solitaire 双向广度搜索
- poj 1198 hdu 1401 搜索+剪枝 Solitaire
- HDU 1401 Solitaire
- HDU 1401 Solitaire
- HDU 1401 Solitaire 双向BFS
- HDU_1401——分步双向BFS,八进制乘权值压缩,map存放hash
- hdu 1401 双向搜索(bfs)
- HDU-1401 Solitaire 搜索