hdu 1401 (双广)
来源:互联网 发布:java图形界面的布局 编辑:程序博客网 时间:2024/04/30 21:20
题意: 在一个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)虽然顺序不同,但都是同一个状态。
代码:
#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(); }}
0 0
- hdu 1401双广
- hdu 1401 (双广)
- HDU 1195 双广
- HDU 3085 双广
- HDU 1401 Solitaire (双向广搜)
- hdu 1026 广搜
- hdu 1548 (广搜)
- HDU 1252 广搜
- HDU 1548 广搜
- HDU 3533 广搜
- Nightmare-HDU-广搜
- POJ-1077 HDU-1043 Eight(单广,双广,启发式搜索)
- hdu 1401 zoj1505 pku 1198 双向广搜
- hdu 1401 双向广搜+8进制压缩状态
- HDU 2209 翻纸牌游戏(双广||状态压缩)
- HDU 1403 Eight&POJ 1077(康拖,A* ,BFS,双广)
- hdu 1072 Nightmare(广搜)
- HDU 1072 Nightmare(广搜)
- 给你一棵二叉树的后序和中序序列,求出它的前序序列(So easy!)
- 教您破解别人QQ密码,手机上的QQ密码能破解吗?
- 《人工智能(智能系统指南,第二版)》读书笔记——7、第六章
- 水波纹
- 替换html里的换行
- hdu 1401 (双广)
- 去除winrar广告
- [Lua基础]操作系统库——Date,Time,Clock
- 搭建Android开发环境问题记录(win7)
- linux 读写文件
- java环境配置
- SSH中用到的设计模式之二——简单工厂
- 【软件工程】文档总结
- Ad hoc