【搜索进阶】hdu 1043 Eight
来源:互联网 发布:淘宝上的k歌麦克风 编辑:程序博客网 时间:2024/05/21 09:11
题目链接: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;}
0 0
- 【搜索进阶】hdu 1043 Eight
- hdu 1043 eight (搜索 + 康托展开)
- hdu 1043 Eight(八数码问题 高级搜索: A* 搜索)
- HDU 3567 Eight II (搜索)
- hdu 1043 poj 1077 Eight Time (搜索&八数码)
- HDU 1043 Eight 八数码问题 A*搜索 启发式算法
- 【HDU 1043】Eight(A*启发式搜索算法)
- HDU 1043 Eight poj 1077 (八数码 启发式搜索)
- HDU 1043 && POJ 1077 Eight bfs || 双向bfs || A*搜索
- hdu 1043 Eight
- HDU 1043 Eight
- 周赛 HDU 1043 Eight
- Hdu 1043 Eight
- HDU 1043 Eight
- HDU 1043 Eight
- HDU 1043 Eight
- HDU 1043 Eight
- hdu 1043 Eight
- dump
- 英语八月结
- poj 1324 Holedox Moving
- netbean 8 反锯齿
- Android Content Provider内容提供者的学习笔记
- 【搜索进阶】hdu 1043 Eight
- 当SocketServer断开或发生Wifi网络变化的时候,SocketClient应该如何处理异常。
- JAVA 学习第二天
- [转]HTML5中Canvas与SVG的画图原理比较
- Linux环境下配置samba服务
- C++设计模式----装饰模式
- 转:Oracle中的rownum不能使用大于>的问题
- 3DMark06分数
- 支持向量机SVM(一)