hdu 1043-Eight(经典八数码问题)(单向广搜 A* 状态压缩)

来源:互联网 发布:getting windows ready 编辑:程序博客网 时间:2024/05/21 22:37

一开始接触这题是在poj上,当时直接单广加A*就0ms水过,但放HDU上就一直TLE,想一想发现如果结果是solvable的话这种方法也会把所有状态都查一遍,那还要算法干嘛,所以就开始通过数学方法解决,不难发现,除x外的数组成的数列无论怎么移动都不会改变原数列的奇偶性,这样就能刷下一大堆多余查询了。

其余细节注意处理好就行。

AC代码(171ms):

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm> #include<queue>#include<cstdlib>#define maxn 1000000using namespace std;typedef int State[9];State st, goal;bool vis[400000];int fahash[400000], to[400000];int len;int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};char cdir[4] = {'u', 'd', 'l', 'r'};int pos1[9][2] = {{0,0},{0,1},{0,2},{1,0},{1,1},{1,2},{2,0},{2,1},{2,2}};int pos2[9][2] = {{2,2},{0,0},{0,1},{0,2},{1,0},{1,1},{1,2},{2,0},{2,1}};struct A {int chash, dis, est, dir;State arry;bool operator < (const A& ot) const {return est==ot.est?dis>ot.dis:est>ot.est;}};int fab[9];void set_in() {fab[0] = 1;for(int i=1; i<9; i++) fab[i] = i*fab[i-1];}int bhash(State s) {int code = 0;for(int i=0; i<9; i++) {int cnt = 0;for(int j=i+1; j<9; j++) if(s[i]>s[j]) cnt++;code += cnt*fab[8-i];}return code;}int getest(State s) {int l = 0;for(int i=0; i<9; i++) if(s[i])l += (abs(pos1[i][0]-pos2[s[i]][0])+abs(pos1[i][1]-pos2[s[i]][1]));return l;}bool inter(int x, int y) {return x>=0&&x<3&&y>=0&&y<3;}int bfs() {A u;priority_queue<A> tree;memcpy(u.arry, st, sizeof(st));u.chash = bhash(st);u.dis = 0;u.est = getest(st);fahash[u.chash] = -1;vis[u.chash] = true;tree.push(u);while(!tree.empty()) {u = tree.top(); tree.pop();if(memcmp(goal, u.arry, sizeof(goal))==0) {len = u.dis;return u.chash;}int z;for(z=0; z<9; z++) if(!u.arry[z]) break;int x = z/3, y = z%3;for(int i=0; i<4; i++) {int nx = x + dir[i][0];int ny = y + dir[i][1];int d = nx*3 + ny;if(inter(nx, ny)) {A v;memcpy(v.arry, u.arry, sizeof(u.arry));swap(v.arry[z], v.arry[d]);v.chash = bhash(v.arry);if(vis[v.chash]) continue;vis[v.chash] = true;v.dis = u.dis+1;v.est = getest(v.arry);tree.push(v);fahash[v.chash] = u.chash;to[v.chash] = i;}}}return 0; //warning}int main() {set_in();char str[55];for(int i=0; i<8; i++) goal[i]=i+1;goal[8]=0;while(gets(str)) {int n = 0;memset(vis, false, sizeof(vis));for(int i=0; i<strlen(str); i++) {if(isalpha(str[i])) st[n++] = 0; elseif(isdigit(str[i])) st[n++] = str[i]-'0';}if(memcmp(goal, st, sizeof(st))==0) {printf("lr\n");continue;}int rev = 0;for(int i=0; i<9; i++) {for(int j=i+1; j<9; j++) if(st[i]&&st[j]&&st[i]>st[j]) rev++;}if(rev&1) {printf("unsolvable\n");continue;}int tt = bfs();char ans[233];if(tt) {ans[len] = '\0';while(fahash[tt]!=-1) {ans[--len] = cdir[to[tt]];tt = fahash[tt];}printf("%s\n", ans);} else {printf("unsolvable\n");}}return 0;}


0 0
原创粉丝点击