【搜索进阶】hdu 1043 Eight
2014-08-28 22:27
232 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043
A*: 因为每次移动都会影响一个点的曼哈顿距离(不算x),构造h()为所有数字块的曼哈顿距离和,用逆序数hash(算x),根据逆序数奇偶性(不算x)减掉无法到达的情况;在构造优先队列时当f相同时按照g值从大到小排序,这样又是一个很给力的减枝
单广预处理: 从最终状态向所有状态搜索,记录前驱,然后直接输出就好
IDA*函数:和A*一样的h()函数,内存占用小是其优势。
A*: 因为每次移动都会影响一个点的曼哈顿距离(不算x),构造h()为所有数字块的曼哈顿距离和,用逆序数hash(算x),根据逆序数奇偶性(不算x)减掉无法到达的情况;在构造优先队列时当f相同时按照g值从大到小排序,这样又是一个很给力的减枝
#include <cstdio> #include <cstring> #include <queue> using namespace std; struct S { char maze[3][3]; int x , y; int g , h , f; S() {} S(const S& ts) { for(int i=0;i<3;i++) for(int j=0;j<3;j++) maze[i][j] = ts.maze[i][j]; x = ts.x; y = ts.y; g = ts.g; h = ts.h; f = ts.f; } friend bool operator < (const S& a,const S& b) { if(a.f == b.f) return a.g < b.g; return a.f > b.f; } }s; const int fac[] = {1,1,2,6,24,120,720,5040,40320}; bool vis[363000]; int pre[363000]; char op[363000]; inline int inv_hash(S ts) { char str[11]; int ans = 0; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { str[i*3+j] = ts.maze[i][j]; int cnt = 0; for(int k=i*3+j-1;k>=0;k--) { if(str[k] > str[i*3+j]) cnt++; } ans += fac[i*3+j] * cnt; } } return ans; } const int pos[][2]={{0,0},{0,1},{0,2},{1,0},{1,1},{1,2},{2,0},{2,1},{2,2}}; inline int abs(int x) { return x < 0 ? -x : x; } inline int h(S ts) { int val = 0; for(int i=0;i<3;i++) for(int j=0;j<3;j++) { if(ts.maze[i][j] == 'x') continue; int c = ts.maze[i][j] - '1'; val += abs(pos[c][0]-i)+abs(pos[c][1]-j); } return val; } const int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}}; bool bfs() { memset(vis,false,sizeof(vis)); priority_queue<S> que; que.push(s); while(!que.empty()) { S u = que.top(); que.pop(); int ihu = inv_hash(u); for(int i=0;i<4;i++) { S v = u; v.x += dir[i][0]; v.y += dir[i][1]; if(v.x<0||v.y<0||v.x>=3||v.y>=3) continue; v.maze[u.x][u.y]=u.maze[v.x][v.y]; v.maze[v.x][v.y]='x'; v.g+=1; v.h=h(v); v.f=v.g+v.h; int ihv = inv_hash(v); if(vis[ihv]) continue; vis[ihv] = true; pre[ihv] = ihu; if(i == 0) op[ihv] = 'd'; else if(i == 1) op[ihv] = 'r'; else if(i == 2) op[ihv] = 'u'; else if(i == 3) op[ihv] = 'l'; if(ihv == 0) return true; que.push(v); } } return false; } inline bool inv_check() { char str[11]; int cnt = 0; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { str[i*3+j] = s.maze[i][j]; if(str[i*3+j] == 'x') continue; for(int k=i*3+j-1;k>=0;k--) { if(str[k]=='x') continue; if(str[k] > str[i*3+j]) cnt++; } } } return !(cnt&1); } char in[111]; char stk[111]; int main() { while(gets(in)) { for(int i=0,x=0,y=0;in[i];i++) { if((in[i]<='9'&&in[i]>='0')||in[i]=='x') { s.maze[x][y] = in[i]; if(in[i]=='x') { s.x=x;s.y=y; } y++; if(y == 3) y=0,x++; } } if(!inv_check()) { puts("unsolvable"); continue; } s.g=0; s.h=h(s); s.f=s.h; int shash = inv_hash(s); if(shash==0) { puts(""); continue; } bfs(); int top = -1 , thash = 0; while(thash != shash) { stk[++top] = op[thash]; thash = pre[thash]; } for(int i=top;i>=0;i--) { putchar(stk[i]); } puts(""); } return 0; }
单广预处理: 从最终状态向所有状态搜索,记录前驱,然后直接输出就好
#include<cstdio> #include<cstring> #include<queue> using namespace std; struct S{ char maze[3][3]; int x,y; S(){} S(const char *str){ for(int i=0,tx=0,ty=0;str[i];i++){ if((str[i]<='9'&&str[i]>='0')||str[i]=='x'){ maze[tx][ty]=str[i]; if(str[i]=='x'){x=tx;y=ty;} ty++; if(ty==3){ty=0;tx++;} } } } }; int pre[363000]; char op[363000]; const int fac[]={1,1,2,6,24,120,720,5040,40320}; bool vis[363000]; inline int inv_hash(S ts){ char str[10]; int ans=0; for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ str[i*3+j]=ts.maze[i][j]; int cnt=0; for(int k=i*3+j-1;k>=0;k--){ if(str[k]>str[i*3+j]) cnt++; } ans+=fac[i*3+j]*cnt; } } return ans; } S s; const int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}}; const char cdir[]="dulr"; void bfs(){ memset(vis,false,sizeof(vis)); memset(pre,-1,sizeof(pre)); queue<S> que; que.push(s); while(!que.empty()){ S u=que.front(); que.pop(); int ihu=inv_hash(u); for(int i=0;i<4;i++){ S v=u; v.x+=dir[i][0]; v.y+=dir[i][1]; if(v.x<0||v.y<0||v.x>=3||v.y>=3) continue; v.maze[u.x][u.y]=v.maze[v.x][v.y]; v.maze[v.x][v.y]='x'; int ihv=inv_hash(v); if(vis[ihv]) continue; vis[ihv]=true; pre[ihv]=ihu; op[ihv]=cdir[i]; que.push(v); } } } char in[100]; char stk[100]; int main(){ s=S("12345678x"); bfs(); while(gets(in)){ s=S(in); int ihs=inv_hash(s); if(pre[ihs]==-1){puts("unsolvable");continue;} if(ihs==0){puts("");continue;} int top=-1,tmp=ihs; while(tmp){ putchar(op[tmp]); tmp=pre[tmp]; } puts(""); } return 0; }
IDA*函数:和A*一样的h()函数,内存占用小是其优势。
#include<cstdio> #include<cstring> using namespace std; struct S{ char maze[3][3]; int x,y; int g,h,f; S(){} S(const S& ts){ for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ maze[i][j]=ts.maze[i][j]; } } x=ts.x; y=ts.y; } void show(){ for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ putchar(maze[i][j]); } puts(""); } } }; const int pos[][2]={{0,0},{0,1},{0,2},{1,0},{1,1},{1,2},{2,0},{2,1},{2,2}}; inline int ABS(int x){ if(x<0) return-x; else return x; } inline int h(S ts){ int val=0; for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ if(ts.maze[i][j]=='x') continue; int c=ts.maze[i][j]-'1'; val+=ABS(pos[c][0]-i)+ABS(pos[c][1]-j); } } return val; } int fac[]={1,1,2,6,24,120,720,5040,40320}; inline int inv_hash(S ts){ char str[10]; int ans=0; for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ str[i*3+j]=ts.maze[i][j]; int cnt=0; for(int k=i*3+j-1;k>=0;k--){ if(str[k]>str[i*3+j]) cnt++; } ans+=fac[i*3+j]*cnt; } } return ans; } int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}}; int ans[50],deep; bool vis[363000]; S ts; bool dfs(int d){ if(h(ts)==0) return true; if(h(ts)+d>deep) return false; int x=ts.x; int y=ts.y; for(int i=0;i<4;i++){ int tx=ts.x+dir[i][0]; int ty=ts.y+dir[i][1]; if(tx<0||ty<0||tx>=3||ty>=3) continue; ts.maze[x][y]=ts.maze[tx][ty]; ts.maze[tx][ty]='x'; int tmp=inv_hash(ts); if(vis[tmp]){ ts.maze[tx][ty]=ts.maze[x][y]; ts.maze[x][y]='x'; continue; } vis[tmp]=true; ts.x=tx; ts.y=ty; ans[d]=i; if(dfs(d+1)) return true; vis[tmp]=false; ts.x=x; ts.y=y; ts.maze[tx][ty]=ts.maze[x][y]; ts.maze[x][y]='x'; } return false; } S s; bool inv_check(){ char str[10]; int cnt=0; for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ str[i*3+j]=s.maze[i][j]; if(str[i*3+j]=='x') continue; for(int k=i*3+j-1;k>=0;k--){ if(str[k]=='x') continue; if(str[k]>str[i*3+j]) cnt++; } } } return!(cnt&1); } char in[100]; int main(){ while(gets(in)){ for(int i=0,x=0,y=0;in[i];i++){ if((in[i]<='9'&&in[i]>='0')||in[i]=='x'){ s.maze[x][y]=in[i]; if(in[i]=='x'){s.x=x;s.y=y;} y++; if(y==3) y=0,x++; } } if(!inv_check()){ puts("unsolvable"); continue;} memset(vis,false,sizeof(vis)); vis[inv_hash(s)]=true; ts=s; deep=0; while(true){ if(dfs(0)) break; deep++; } for(int i=0;i<deep;i++){ if(ans[i]==0) putchar('d'); else if(ans[i]==1) putchar('r'); else if(ans[i]==2) putchar('u'); else if(ans[i]==3) putchar('l'); } puts(""); } return 0; }
相关文章推荐
- hdu 1043 eight (搜索 + 康托展开)
- HDU-1043 Eight八数码 搜索问题(bfs+hash 打表 IDA* 等)
- hdu 1043/poj 1077 Eight (八数码 经典搜索题 bfs + 康托展开)
- hdu 1043 Eight 搜索,哈希
- hdu 1043 Eight(八数码问题 高级搜索: A* 搜索)
- HDU 1043 Eight 八数码问题 A*搜索 启发式算法
- [搜索] hdu1043 Eight(8思路)
- Hdu1043 Eight 【A*搜索】八数码问题
- HDU 1043 && POJ 1077 Eight bfs || 双向bfs || A*搜索
- HDU-1043 Eight 八数码问题
- 周赛 HDU 1043 Eight
- 【搜索进阶】HDU 1667 The Rotation Game
- POJ 1077 HDU 1043 Eight (IDA*)
- HDU 1043 八数码问题 A*搜索
- 【搜索进阶】HDU 1560 DNA sequence
- HDU - 1043 - Eight / POJ - 1077 - Eight
- hdu 1043 Eight 双向BFS/A*算法
- HDU 1043 ,POJ 1077 Eight
- HDU 1043 搜索+康托展开
- poj 1077 & hdu 1043 Eight ( 多种解法:预处理、bfs、dbfs、IDA*、A*)