HDU 3095 哈希+双向搜索
2016-07-22 16:22
323 查看
题意:求从给出的状态到达目标状态需要多少步,无法到达或大于20输出No solution!解题思路:哈希+双向搜索,好长呦。代码: <pre name="code" class="cpp">#include<cstdio> #include<cstring> #include<string> #include<iostream> #include<sstream> #include<algorithm> #include<utility> #include<vector> #include<set> #include<map> #include<queue> #include<cmath> #include<iterator> #include<stack> using namespace std; const int INF=1e9+7; const double eps=1e-7; const int mod=1000007; const int maxn=5000000; int f[2],r[2]; int dx[]={-1,0,1,0},dy[]={0,-1,0,1}; int qq; bool in(int x,int y){ return x>=0&&x<5&&y>=0&&y<5; } struct node { int px[2],py[2]; int A[5][5]; }nod[2][maxn]; int B[5][5]={ -1,-1,0,-1,-1, -1,1,2,3,-1, 4,5,6,7,8, -1,9,10,11,-1, -1,-1,0,-1,-1 }; bool Same(int A[][5]) { for(int i=0;i<5;i++) for(int j=0;j<5;j++) if(A[i][j]!=B[i][j]) return false; return true; } int F[20]; //??2^i void GetF() { F[0]=1; for(int i=1;i<15;i++) F[i]=F[i-1]*2; } int Get(int A[][5]) { int ret=0,k=0; for(int i=0;i<5;i++) for(int j=0;j<5;j++) if(A[i][j]>0) ret+=F[k++]*A[i][j]; return ret; } struct Hash { int v,next,nid,k; }ha[mod+maxn]; int hash_id; bool check(int a,int k1,int b,int k2) { for(int i=0;i<5;i++) for(int j=0;j<5;j++) if(nod[k1][a].A[i][j]!=nod[k2][b].A[i][j]) return false; return true; } int Insert_Hash(int v,int nid,int k) { int a=v%mod; int p=ha[a].next; while(p!=-1) { if(check(ha[p].nid , ha[p].k , nid , k)) return ha[p].k; p=ha[p].next; } p=++hash_id; ha[p].v=v; ha[p].nid=nid; ha[p].k=k; ha[p].next=ha[a].next; ha[a].next=p; return -1; } bool AddNode(node t,int i,int j,int k) { int x=t.px[i],y=t.py[i]; int nx=x+dx[j],ny=y+dy[j]; if(!in(nx,ny)||t.A[nx][ny]<=0) return false; node& tt=nod[k][r[k]]; tt=t; swap(tt.A[x][y],tt.A[nx][ny]); tt.px[i]=nx; tt.py[i]=ny; int a=Insert_Hash(Get(tt.A),r[k],k); if(a==-1){ r[k]++; return false; } else if(a==k) return false; else return true; } void Print(node& t) { for(int i=0;i<5;i++) { for(int j=0;j<5;j++) printf("%d ",t.A[i][j]); puts(""); } puts("========="); getchar(); } bool bfs(int k) { int& be=f[k]; int en=r[k]; while(be<en) { node t=nod[k][be++]; for(int i=0;i<2;i++) for(int j=0;j<4;j++) if(AddNode(t,i,j,k)) return true; } return false; } int solve() { if(Same(nod[0][0].A)) return 0; for(int i=0;i<5;i++) for(int j=0;j<5;j++) nod[1][0].A[i][j]=B[i][j]; nod[1][0].px[0]=0; nod[1][0].py[0]=2; nod[1][0].px[1]=4; nod[1][0].py[1]=2; int step=0; f[0]=f[1]=0,r[0]=r[1]=1; for(int i=0;i<mod;i++) ha[i].next=-1; hash_id=mod; while(f[0]<r[0]||f[1]<r[1]) { step++; if(bfs(0)) return step; step++; if(bfs(1)) return step; if(step>=20) { // cout<<step<<endl; return -1; } } return -1; } int main() { int T; GetF(); scanf("%d",&T); while(T--) { qq=20; int k=0; for(int i=0;i<5;i++) for(int j=0;j<5;j++) { if(B[i][j]==-1) { nod[0][0].A[i][j]=-1; continue; } scanf("%d",&nod[0][0].A[i][j]); if(nod[0][0].A[i][j]==0) { nod[0][0].px[k]=i; nod[0][0].py[k++]=j; } } int ans=solve(); if(ans==-1) printf("No solution!\n"); else printf("%d\n",ans); } return 0; } |
相关文章推荐
- 使用无符号右移-&-栈 实现 十进制转十六进制
- 看板方法整理
- leetcode_c++:栈:Min Stack(155)
- Floyed算法求多源最短路径
- 10以内的简单计算
- 易流专线货运物流软件 V14.02 网络版
- Android和Untiy3D的交互方式
- 《WINDOWSPE权威指南》学习笔记(一)-U盘监控器的破解
- Css:背景色透明,内容不透明之终极方法!兼容所有浏览器
- PostgreSQL学习----命令或问题小结
- POJ 3252 - Round Numbers(数位dp)
- UITextView 行间距设置以及placeholder
- nginx配置
- serialVersionUID的作用
- 正则表达式
- TAIGA 部署
- golang守护进程用法示例
- 数字特征值-week3-C语言习题集
- poj1062 昂贵的聘礼 (最短路)
- png-24在ie6中的几种透明方法