POJ 1077 HDU 1043 Eight (IDA*)
来源:互联网 发布:银行卡照片制作软件 编辑:程序博客网 时间:2024/06/05 05:29
题意就不用再说明了吧......如此经典
之前想用双向广搜、a*来写,但总觉得无力,现在用IDA*感觉其他的解法都弱爆了..............想法活跃,时间,空间消耗很小,给它跪了
启发式搜索关键还是找估价函数:此题估价函数可大致定性为每个数字(除去x,只要8个数字)当前位置与它期望位置的曼哈顿距离
即为:v += abs(i - pos[map[i][j] - 1][0]); v += abs(j - pos[map[i][j] - 1][1]); 大致估算为几十步内得出结果。
#include <iostream>#include <algorithm>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <vector>#include <set>#include <queue>#include <stack>#include <climits>//形如INT_MAX一类的#define MAX 100005#define INF 0x7FFFFFFF#define REP(i,s,t) for(int i=(s);i<=(t);++i)#define ll long long#define mem(a,b) memset(a,b,sizeof(a))#define mp(a,b) make_pair(a,b)#define L(x) x<<1#define R(x) x<<1|1# define eps 1e-5//#pragma comment(linker, "/STACK:36777216") ///传说中的外挂using namespace std;int pos[9][2] = { //各个数字的初始位置 {0,0},{0,1},{0,2}, {1,0},{1,1},{1,2}, {2,0},{2,1},{2,2}};int map[4][4];int buff[50];char input[11];int limit,ok;int dx[] = {-1,0,1,0}; //u r d l____0 1 2 3int dy[] = {0,1,0,-1};char op[] = {'u','r','d','l'};int h(int x,int y) { int v = 0; for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { if(i != x || j != y) { v += abs(i - pos[map[i][j] - 1][0]); v += abs(j - pos[map[i][j] - 1][1]); } } } return v;}int dfs(int x,int y,int step,int pre) { int hn = h(x,y); if(hn == 0) { ok = 1; return step; } if(hn + step > limit) return hn + step; int minn = INF; for(int i=0; i<4; i++) { if(abs(i - pre) == 2) continue; int xx = x + dx[i]; int yy = y + dy[i]; if(xx<0 || xx >=3 || yy<0 || yy >=3) continue; buff[step] = i; swap(map[x][y],map[xx][yy]); int tmp = dfs(xx,yy,step+1,i); if(ok) return tmp; minn = min(tmp,minn); swap(map[x][y],map[xx][yy]); } return minn;}void IDA_star(int x,int y) { ok = 0; memset(buff,-1,sizeof(buff)); while(ok == 0 && limit <= 36) { limit = dfs(x,y,0,-111); } if(ok == 1) { for(int i=0; i<limit; i++) printf("%c",op[buff[i]]); puts(""); } else puts("unsolvable");}int main() { for(int i=0; i<9; i++) cin >> input[i]; int t = 0,x,y; for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { if(input[t] == 'x') { map[i][j] = 9; x = i; y = j; t++; } else map[i][j] = input[t++] - '0'; } } int limit = h(x,y); if(limit == 0) { puts(""); return 0; } IDA_star(x,y); return 0;}
想吐槽一下杭电的这题.........估计各种无法到达目标的数据,所以在输入时候通过求逆序数对数来判断是否有解,本来是TLE,一下蹦到171ms
#include <iostream>#include <algorithm>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <vector>#include <set>#include <queue>#include <stack>#include <climits>//形如INT_MAX一类的#define MAX 100005#define INF 0x7FFFFFFF#define REP(i,s,t) for(int i=(s);i<=(t);++i)#define ll long long#define mem(a,b) memset(a,b,sizeof(a))#define mp(a,b) make_pair(a,b)#define L(x) x<<1#define R(x) x<<1|1# define eps 1e-5//#pragma comment(linker, "/STACK:36777216") ///传说中的外挂using namespace std;int pos[9][2] = { //各个数字的初始位置 {0,0},{0,1},{0,2}, {1,0},{1,1},{1,2}, {2,0},{2,1},{2,2}};int map[4][4];int buff[50];char input[11];int limit,ok;int dx[] = {-1,0,1,0}; //u r d l____0 1 2 3int dy[] = {0,1,0,-1};char op[] = {'u','r','d','l'};int h(int x,int y) { int v = 0; for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { if(i != x || j != y) { v += abs(i - pos[map[i][j] - 1][0]); v += abs(j - pos[map[i][j] - 1][1]); } } } return v;}int dfs(int x,int y,int step,int pre) { int hn = h(x,y); if(hn == 0) { ok = 1; return step; } if(hn + step > limit) return hn + step; int minn = INF; for(int i=0; i<4; i++) { if(abs(i - pre) == 2) continue; int xx = x + dx[i]; int yy = y + dy[i]; if(xx<0 || xx >=3 || yy<0 || yy >=3) continue; buff[step] = i; swap(map[x][y],map[xx][yy]); int tmp = dfs(xx,yy,step+1,i); if(ok) return tmp; minn = min(tmp,minn); swap(map[x][y],map[xx][yy]); } return minn;}int canget(int a[4][4]) { //这一步省了好多时间 求逆序数对数 int i,j,sum=0,b[10],k=0; for(i=0; i<3; i++) { for(j=0; j<3; j++) { if(a[i][j] != 9) b[++k]=a[i][j]; } } for(i=1; i<=8; i++) { for(j=1; j<i; j++) { if(b[i]<b[j])sum++; } } if(sum % 2 ==0)return 1; else return 0;}void IDA_star(int x,int y) { ok = 0; memset(buff,-1,sizeof(buff)); while(ok == 0 && limit <= 30) { limit = dfs(x,y,0,-111); } if(ok == 1) { for(int i=0; i<limit; i++) printf("%c",op[buff[i]]); puts(""); } else puts("unsolvable");}int main() { while(cin >> input[0]) { //memset(map,0,sizeof(map)); for(int i=1; i<9; i++) cin >> input[i]; int t = 0,x,y; for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { if(input[t] == 'x') { map[i][j] = 9; x = i; y = j; t++; } else map[i][j] = input[t++] - '0'; } } limit = h(x,y); if(limit == 0) { puts(""); continue; } if(canget(map)) IDA_star(x,y); else puts("unsolvable"); } return 0;}
经过猥琐的测试,limit最小限制在29步....................
- POJ 1077 HDU 1043 Eight (IDA*)
- POJ 1077 Eight IDA*
- poj 1077-Eight;hdu 1043-Eight
- poj 1077 & hdu 1043 Eight ( 多种解法:预处理、bfs、dbfs、IDA*、A*)
- HDU 1043 ,POJ 1077 Eight
- poj 1077 Eight (bfs A* IDA*)
- [HDU 1043] Eight A*或IDA*
- poj 1077 + HOJ 10466 + hdu 1043 eight
- HDU 1043 && POJ 1077 Eight (A*)
- POJ 1077 Eight A*算法 IDA*算法 康拓展开
- POJ 1077 Eight(八数码A*+IDA*)
- POJ 1077 Eight & HDU 1043 Eight(康托展开+BFS)
- POJ 1077 Eight && HDU 1043 Eight 八数码问题(A*算法)
- hdu 1043 poj 1077 Eight Time (搜索&八数码)
- HDU 1043 / POJ 1077 Eight(八数码问题)
- HDU 1043 Eight poj 1077 (八数码 启发式搜索)
- POJ 1077(HDU 1043)Eight(八数码DBFS)
- HDU 1043 && POJ 1077 Eight bfs || 双向bfs || A*搜索
- python手记(36)
- 快捷方式的添加与删除
- Unity3D精简版网络游戏雏形(简单网络通信聊天和角色监视案例)
- jQuery UI调用draggable之后无法拖拽的解决办法
- Linux Kernel 之AP读写Nand Flash上的Yaffs2文件的全过程浅析
- POJ 1077 HDU 1043 Eight (IDA*)
- hdu - 1757 - A Simple Math Problem(矩阵快速幂)
- xp+ubuntu8.10双系统启动顺序修改
- 最小角回归(Least Angle Regression)
- Python之lxml
- 常见凸多边形判断方法
- Java的四种引用
- 吐槽-android4高级编程(第三版)(中文版)之getQuantityString
- POJ 3260 The Fewest Coins