poj 1077 Eight (BFS)
来源:互联网 发布:淘宝网账号登录历史 编辑:程序博客网 时间:2024/05/24 01:38
八数码问题,各种解法。
/*// BFS#include<iostream>#include<cstdio>#include<queue>using namespace std;// 把1..n的排列映射为数字 0..(n!-1)int fac[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };//...int order(const char *s, int n) { int i, j, temp, num; num = 0; for (i = 0; i < n-1; i++) { temp = 0; for (j = i + 1; j < n; j++) { if (s[j] < s[i]) temp++; } num += fac[s[i] -1] * temp; } return num;}bool is_equal(const char *b1, const char *b2){ for(int i=0; i<9; i++) if(b1[i] != b2[i]) return false; return true;}//hashstruct node{ char board[9]; char space;//空格所在位置};const int TABLE_SIZE = 362880;int hash(const char *cur){ return order(cur, 9);}// 整数映射成排列void get_node(int num, node &tmp) { int n=9; int a[9]; //求逆序数 for (int i = 2; i <= n; ++i) { a[i - 1] = num % i; num = num / i; tmp.board[i - 1] = 0;//初始化 } tmp.board[0] = 0; int rn, i; for (int k = n; k >= 2; k--) { rn = 0; for (i = n - 1; i >= 0; --i) { if (tmp.board[i] != 0) continue; if (rn == a[k - 1]) break; ++rn; } tmp.board[i] = k; } for (i = 0; i < n; ++i) if (tmp.board[i] == 0) { tmp.board[i] = 1; break; } tmp.space = n - a[n-1] -1;}char visited[TABLE_SIZE];int parent[TABLE_SIZE];char move[TABLE_SIZE];int step[4][2] = {{-1, 0},{1, 0}, {0, -1}, {0, 1}};//u, d, l, rvoid BFS(const node & start){ int x, y, k, a, b; int u, v; for(k=0; k<TABLE_SIZE; ++k) visited[k] = 0; u = hash(start.board); parent[u] = -1; visited[u] = 1; queue<int> que; que.push(u); node tmp, cur; while(!que.empty()){ u = que.front(); que.pop(); get_node(u, cur); k = cur.space; x = k / 3; y = k % 3; for(int i=0; i<4; ++i){ a = x + step[i][0]; b = y + step[i][1]; if(0<=a && a<=2 && 0<=b && b<=2){ tmp = cur; tmp.space = a*3 + b; swap(tmp.board[k], tmp.board[tmp.space]); v = hash(tmp.board); if(visited[v] != 1){ move[v] = i; visited[v] = 1; parent[v] = u; if(v == 0) //目标结点hash值为0 return; que.push(v); } } } }}void print_path(){ int n, u; char path[1000]; n = 1; path[0] = move[0]; u = parent[0]; while(parent[u] != -1){ path[n] = move[u]; ++n; u = parent[u]; } for(int i=n-1; i>=0; --i){ if(path[i] == 0) printf("u"); else if(path[i] == 1) printf("d"); else if(path[i] == 2) printf("l"); else printf("r"); }}int main(){// freopen("in", "r", stdin); node start; char c; for(int i=0; i<9; ++i){ cin>>c; if(c == 'x'){ start.board[i] = 9; start.space = i; } else start.board[i] = c - '0'; } BFS(start); if(visited[0] == 1) print_path(); else printf("unsolvable"); return 0;}// A*#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<queue>using namespace std;// 把1..n的排列映射为数字 0..(n!-1)int fac[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };//...int order(const char *s, int n) { int i, j, temp, num; num = 0; for (i = 0; i < n-1; i++) { temp = 0; for (j = i + 1; j < n; j++) { if (s[j] < s[i]) temp++; } num += fac[s[i] -1] * temp; } return num;}bool is_equal(const char *b1, const char *b2){ for(int i=0; i<9; i++) if(b1[i] != b2[i]) return false; return true;}//hashstruct node{ char board[9]; char space;//空格所在位置};const int TABLE_SIZE = 362880;int hash(const char *cur){ return order(cur, 9);}// 整数映射成排列void get_node(int num, node &tmp) { int n=9; int a[9]; //求逆序数 for (int i = 2; i <= n; ++i) { a[i - 1] = num % i; num = num / i; tmp.board[i - 1] = 0;//初始化 } tmp.board[0] = 0; int rn, i; for (int k = n; k >= 2; k--) { rn = 0; for (i = n - 1; i >= 0; --i) { if (tmp.board[i] != 0) continue; if (rn == a[k - 1]) break; ++rn; } tmp.board[i] = k; } for (i = 0; i < n; ++i) if (tmp.board[i] == 0) { tmp.board[i] = 1; break; } tmp.space = n - a[n-1] -1;}//启发函数: 除去x之外到目标的网格距离和int goal_state[9][2] = {{0,0}, {0,1}, {0,2}, {1,0}, {1,1}, {1,2}, {2,0}, {2,1}, {2,2}};int h(const char *board){ int k; int hv = 0; for(int i=0; i<3; ++i) for(int j=0; j<3; ++j){ k = i*3+j; if(board[k] != 9){ hv += abs(i - goal_state[board[k]-1][0]) + abs(j - goal_state[board[k] -1][1]); } } return hv;}int f[TABLE_SIZE], d[TABLE_SIZE];//估计函数和深度//优先队列的比较对象struct cmp{ bool operator () (int u, int v){ return f[u] > f[v]; }};char color[TABLE_SIZE];//0, 未访问;1, 在队列中,2, closedint parent[TABLE_SIZE];char move[TABLE_SIZE];int step[4][2] = {{-1, 0},{1, 0}, {0, -1}, {0, 1}};//u, d, l, rvoid A_star(const node & start){ int x, y, k, a, b; int u, v; priority_queue<int, vector<int>, cmp> open; memset(color, 0, sizeof(char) * TABLE_SIZE); u = hash(start.board); parent[u] = -1; d[u] = 0; f[u] = h(start.board); open.push(u); color[u] = 1; node tmp, cur; while(!open.empty()){ u = open.top(); if(u == 0) return; open.pop(); get_node(u, cur); k = cur.space; x = k / 3; y = k % 3; for(int i=0; i<4; ++i){ a = x + step[i][0]; b = y + step[i][1]; if(0<=a && a<=2 && 0<=b && b<=2){ tmp = cur; tmp.space = a*3 + b; swap(tmp.board[k], tmp.board[tmp.space]); v = hash(tmp.board); if(color[v] == 1 && (d[u] + 1) < d[v]){//v in open move[v] = i; f[v] = f[v] - d[v] + d[u] + 1;//h[v]已经求过 d[v] = d[u] + 1; parent[v] = u; //直接插入新值, 有冗余,但不会错 open.push(v); } else if(color[v] == 2 && (d[u]+1)<d[v]){//v in closed move[v] = i; f[v] = f[v] - d[v] + d[u] + 1;//h[v]已经求过 d[v] = d[u] + 1; parent[v] = u; open.push(v); color[v] = 1; } else if(color[v] == 0){ move[v] = i; d[v] = d[u] + 1; f[v] = d[v] + h(tmp.board); parent[v] = u; open.push(v); color[v] = 1; } } } color[u] = 2; // }}void print_path(){ int n, u; char path[1000]; n = 1; path[0] = move[0]; u = parent[0]; while(parent[u] != -1){ path[n] = move[u]; ++n; u = parent[u]; } for(int i=n-1; i>=0; --i){ if(path[i] == 0) printf("u"); else if(path[i] == 1) printf("d"); else if(path[i] == 2) printf("l"); else printf("r"); }}int main(){ //freopen("in", "r", stdin); node start; char c; for(int i=0; i<9; ++i){ cin>>c; if(c == 'x'){ start.board[i] = 9; start.space = i; } else start.board[i] = c - '0'; } A_star(start); if(color[0] != 0) print_path(); else printf("unsolvable"); return 0;}// IDA*#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;#define SIZE 3char board[SIZE][SIZE];//启发函数: 除去x之外到目标的网格距离和int goal_state[9][2] = {{0,0}, {0,1}, {0,2}, {1,0}, {1,1}, {1,2}, {2,0}, {2,1}, {2,2}};int h(char board[][SIZE]){ int cost = 0; for(int i=0; i<SIZE; ++i) for(int j=0; j<SIZE; ++j){ if(board[i][j] != SIZE*SIZE){ cost += abs(i - goal_state[board[i][j]-1][0]) + abs(j - goal_state[board[i][j]-1][1]); } } return cost;}int step[4][2] = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};//u, l, r, dchar op[4] = {'u', 'l', 'r', 'd'};char solution[1000];int bound; //上界bool ans; //是否找到答案int DFS(int x, int y, int dv, char pre_move){// 返回next_bound int hv = h(board); if(hv + dv > bound) return dv + hv; if(hv == 0){ ans = true; return dv; } int next_bound = 1e9; for(int i=0; i<4; ++i){ if(i + pre_move == 3)//与上一步相反的移动 continue; int nx = x + step[i][0]; int ny = y + step[i][1]; if(0<=nx && nx<SIZE && 0<=ny && ny<SIZE){ solution[dv] = i; swap(board[x][y], board[nx][ny]); int new_bound = DFS(nx, ny, dv+1, i); if(ans) return new_bound; next_bound = min(next_bound, new_bound); swap(board[x][y], board[nx][ny]); } } return next_bound;}void IDA_star(int sx, int sy){ ans = false; bound = h(board);//初始代价 while(!ans && bound <= 100)//上限 bound = DFS(sx, sy, 0, -10);}int main(){ freopen("in", "r", stdin); int sx, sy;//起始位置 char c; for(int i=0; i<SIZE; ++i) for(int j=0; j<SIZE; ++j){ cin>>c; if(c == 'x'){ board[i][j] = SIZE * SIZE; sx = i; sy = j; } else board[i][j] = c - '0'; } IDA_star(sx, sy); if(ans){ for(int i=0; i<bound; ++i) cout<<op[solution[i]]; } else cout<<"unsolvable"; return 0;}*/#include<stdio.h>#include<queue>#include<string.h>#include<iostream>#include<algorithm>using namespace std;const int MAXN=1000000;int fac[]={1,1,2,6,24,120,720,5040,40320,362880};//康拖展开判重// 0!1!2!3! 4! 5! 6! 7! 8! 9!bool vis[MAXN];//标记int cantor(int s[])//康拖展开求该序列的hash值{ int sum=0; for(int i=0;i<9;i++) { int num=0; for(int j=i+1;j<9;j++) if(s[j]<s[i])num++; sum+=(num*fac[9-i-1]); } return sum+1;}struct Node{ int s[9]; int loc;//“0”的位置,把“x"当0 int status;//康拖展开的hash值 string path;//路径};string path;int aim=46234;//123456780对应的康拖展开的hash值int move[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//u,d,l,rchar indexs[5]="udlr";//正向搜索Node ncur;bool bfs(){ memset(vis,false,sizeof(vis)); Node cur,next; queue<Node>q; q.push(ncur); while(!q.empty()) { cur=q.front(); q.pop(); if(cur.status==aim) { path=cur.path; return true; } int x=cur.loc/3; int y=cur.loc%3; for(int i=0;i<4;i++) { int tx=x+move[i][0]; int ty=y+move[i][1]; if(tx<0||tx>2||ty<0||ty>2)continue; next=cur; next.loc=tx*3+ty; next.s[cur.loc]=next.s[next.loc]; next.s[next.loc]=0; next.status=cantor(next.s); if(!vis[next.status]) { vis[next.status]=true; next.path=next.path+indexs[i]; if(next.status==aim) { path=next.path; return true; } q.push(next); } } } return false;}int main(){ char ch; while(cin>>ch) { if(ch=='x') {ncur.s[0]=0;ncur.loc=0;} else ncur.s[0]=ch-'0'; for(int i=1;i<9;i++) { cin>>ch; if(ch=='x') { ncur.s[i]=0; ncur.loc=i; } else ncur.s[i]=ch-'0'; } ncur.status=cantor(ncur.s); if(bfs()) { cout<<path<<endl; } else cout<<"unsolvable"<<endl; } return 0;}
0 0
- poj 1077 Eight (BFS)
- POJ 1077 Eight BFS -
- poj 1077 Eight(BFS + 康托判重)
- POJ 1077 Eight(BFS Hash)
- POJ 1077 Eight(BFS八数码问题)
- poj 1077 Eight (bfs A* IDA*)
- POJ 1077 Eight(BFS:输出路径)
- POJ 1077 Eight 八数码问题 BFS
- POJ 1077-Eight(BFS+优先队列)
- POJ 1077 Eight(康拓展开 BFS 双向BFS)
- HDU 1043 && POJ 1077 Eight bfs || 双向bfs || A*搜索
- pku 1077 Eight BFS
- [POJ]1077 Eight 八数码:康托展开+BFS
- POJ 1077 Eight BFS + 康拓展开式
- POJ:1077 Eight(双向BFS+判重)
- HDU 1403 Eight&POJ 1077(康拖,A* ,BFS,双广)
- poj 1077 Eight(经典八数码问题:bfs/Dbfs)
- POJ 1077 Eight 八数码问题[康托展开 + BFS]
- Android内存分析工具
- 安装spyder python时 出现的问题
- C++中特殊的成员变量的初始化方法
- hdu 3037(Lucas定理,大组合数取模)
- java异常笔记
- poj 1077 Eight (BFS)
- 2014届第一场排位赛
- myBatis学习笔记(8)—— 一级缓存&二级缓存
- 用户反馈信息textbox填充数据表,页面使用gridview显示反馈意见
- Centos安装DDD调试器
- js_day2
- 回归之作-日报
- mysql入门命令
- IOS视图之基础整理