POJ 1077(HDU 1043) Eight(八数码A*算法)
2016-08-24 08:12
549 查看
通过演算发现每次一动,逆序对增加一定是偶数对,如果出现奇数则肯定不符合要求,所以要事先判断否则会超时。奇偶剪枝是一种非常常用的剪枝方法,如果在搜索中超时,可以尝试奇偶剪枝。
八数码问题中是0~8的9个数字,如果当做排列是不能算0的,相当于1~8的8位数字的排列,当左右移动时,1~8的排列,没有改变,当上下移动时,上下的数字走到0的位置都要经过2次的交换,所以交换是偶数次的,那么不改变排列的奇偶性,1~8的标准排列逆序对是0,那么标准排列是偶排列,如果八数码排列是奇排列,那么直接剪枝。
八数码问题中是0~8的9个数字,如果当做排列是不能算0的,相当于1~8的8位数字的排列,当左右移动时,1~8的排列,没有改变,当上下移动时,上下的数字走到0的位置都要经过2次的交换,所以交换是偶数次的,那么不改变排列的奇偶性,1~8的标准排列逆序对是0,那么标准排列是偶排列,如果八数码排列是奇排列,那么直接剪枝。
// // main.cpp // Richard // // Created by 邵金杰 on 16/8/24. // Copyright © 2016年 邵金杰. All rights reserved. // #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cmath> using namespace std; const int maxn=400000; struct node{ int sta[9]; int f,g,h; int pos; int hash; bool operator < (const node &e) const { return f>e.f; } }; int vis[maxn]; int End[9]={1,2,3,4,5,6,7,8,0}; int ha[9]={1,1,2,6,24,120,720,5040,40320}; struct pre{ int pre; char ch; }pr[maxn]; int get_hash(int a[9]) { int res=0; for(int i=0;i<9;i++) { int k=0; for(int j=i+1;j<9;j++) { if(a[j]<a[i]) k++; } res+=k*ha[8-i]; } return res; } int get_h(int a[9]) { int dist=0; for(int i=0;i<9;i++) { int x1=i/3,y1=i%3; int x2,y2; for(int j=0;j<9;j++) { if(End[j]==a[i]) {x2=j/3;y2=j%3;break;} } dist+=(x1-x2>0?x1-x2:-(x1-x2)); dist+=(y1-y2>0?y1-y1:-(y1-y2)); } return dist; } bool reverse(node s) { int times=0; for(int i=0;i<9;i++) { if(s.sta[i]==0) continue; for(int j=i+1;j<9;j++) { if(s.sta[j]==0) continue; if(s.sta[i]>s.sta[j]) times++; } } return times&1; } bool inside(int x,int y) { if(x>=0&&x<=2&&y>=0&&y<=2) return true; return false; } int dx[4]={0,-1,0,1}; int dy[4]={-1,0,1,0}; char d[5]="lurd"; void swap(int *a,int pos1,int pos2) { int temp=a[pos1]; a[pos1]=a[pos2]; a[pos2]=temp; } void print(int x) { if(pr[x].pre==-1) return ; print(pr[x].pre); printf("%c",pr[x].ch); } void Astar(node s) { int end_hash=get_hash(End); if(end_hash==s.hash) {printf("\n");return ;} memset(vis,0,sizeof(vis)); vis[s.hash]=1; pr[s.hash].pre=-1; priority_queue<node> pq; pq.push(s); node p,q; while(!pq.empty()) { p=pq.top(); pq.pop(); int x=p.pos/3,y=p.pos%3; for(int i=0;i<4;i++) { int nx=x+dx[i]; int ny=y+dy[i]; if(!inside(nx,ny)) continue; q=p; swap(q.sta,x*3+y,nx*3+ny); q.hash=get_hash(q.sta); if(vis[q.hash]) continue; vis[q.hash]=1; q.pos=nx*3+ny; q.g++; q.h=get_h(q.sta); q.f=q.g+q.h; pr[q.hash].pre=p.hash; pr[q.hash].ch=d[i]; if(q.hash==end_hash) {print(end_hash);printf("\n");return ;} pq.push(q); } } } int main() { char str[100]; while(gets(str)) { int len=(int)strlen(str); node s; int k=0; int flag=0; for(int i=0;i<len;i++) { if(str[i]==' ') continue; if(str[i]=='x') {flag=k;s.sta[k++]=0;} else s.sta[k++]=str[i]-'0'; } if(reverse(s)) { printf("unsolvable\n"); continue; } s.g=0; s.h=get_h(s.sta); s.f=s.g+s.h; s.hash=get_hash(s.sta); s.pos=flag; Astar(s); } return 0; }
相关文章推荐
- POJ 1077 Eight && HDU 1043 Eight 八数码问题(A*算法)
- HDU 1043 Eight(经典八数码问题)对比POJ 1077
- poj 1077 hdu 1043 Eight 八数码问题 DBFS(双向广度优先搜索)a*算法 康拓展开
- hdu 1034 & poj 1077 Eight 传说中的八数码问题。真是一道神题,A*算法+康托展开
- hdu 1043/poj 1077 Eight (八数码 经典搜索题 bfs + 康托展开)
- POJ 1077(HDU 1043)Eight(八数码DBFS)
- HDU 1043 / POJ 1077 Eight(八数码问题)
- hdu 1043 ,pku 1077 Eight ,八数码问题
- POJ-1077 HDU-1043 Eight(单广,双广,启发式搜索)
- poj 1077-Eight;hdu 1043-Eight
- poj 1077-Eight;hdu 1043-Eight
- HDU 1043 ,POJ 1077 Eight
- hdu 1034 & poj 1077 Eight 传说中的八数码问题。真是一道神题,A*算法+康托展开
- HDU 1043 && POJ 1077 Eight (A*)
- hdu 1043 /poj 1077 Eight(经典八数码问题,BFS+康托展开)
- bfs+hash poj 1077/hdu 1043 八数码问题
- BFS(八数码) POJ 1077 || HDOJ 1043 Eight
- 八数码[POJ-1077 | HDU-1043] BFS A* IDA* 双广
- poj 1077 zoj 1217 hdu 1043 八数码
- hdu 1043 eight(poj 1077) (bfs)