看了这篇博客的讲解,挺不错的。http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html

判断无解的情况(写完七种境界才发现有直接判断无解的方法):

一个状态表示成一维的形式,求出除0之外所有数字的逆序数之和,也就是每个数字前面比它大的数字的个数的和,称为这个状态的逆序。

若两个状态的逆序奇偶性相同,则可相互到达,否则不可相互到达。

POJ提交记录(从下往上依次为第1,2,3,4,5,6,7,8境界):

HDU提交记录(从下往上依次为第1,2,3,4,5,6,7,8境界):

PS:因为HDU是多组测试数据,所以一般POJ上要100ms以上才能AC的方法,在HDU上是无法通过的(境界3除外)

境界一、 暴力广搜+STL (HDU 内存超限,POJ 时间超限)

map存路径,set判重,string存状态,毫无疑问,炸了。

#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<algorithm>
#include<iostream>
using namespace std; char input[];
int dir[][] = { { -, },{ , },{ ,- },{ , } };
string d = "durl";
set<string>f;
map<string, string>m;
int sz = ; struct node
{
string s;
string path;
int pos; node() {}
node(string str, string pa, int Pos)
{
s = str;
path = pa;
pos = Pos;
}
}; bool g(int a, int b)
{
if (a >= && a <= && b >= && b <= ) return ;
return ;
} void pre()
{
queue<node>q;
q.push(node("12345678x", "", ));
m["12345678x"] = "";
f.insert("12345678x"); while (!q.empty())
{
node h = q.front(); q.pop();
int a = h.pos / , b = h.pos % ;
for (int i = ; i<; i++)
{
int x = a + dir[i][], y = b + dir[i][];
if (!g(x, y)) continue;
int pos = * x + y;
swap(h.s[h.pos], h.s[pos]);
if (f.find(h.s) != f.end())
{
swap(h.s[h.pos], h.s[pos]);
continue;
}
q.push(node(h.s, d[i] + h.path, pos));
f.insert(h.s);
m[h.s] = d[i] + h.path;
swap(h.s[h.pos], h.s[pos]);
}
} } int main()
{
pre();
while(~scanf("%s",input))
{
string v="";
v = v + input[];
for (int i = ; i <= ; i++)
{
scanf("%s", input);
v = v + input[];
}
if (m[v] == "") cout << "unsolvable" << endl;
else cout << m[v] << endl;
} return ;
}

境界二、广搜+哈希(POJ 453ms)

利用康托展开对状态进行hash,hash值对应0--(9!-1),因此可以开数组判重,路径的记录可以记录到达某状态的最后一步操作是什么与父节点是什么。

从输入的状态开始进行BFS,直到找到最终状态。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std; char t[];
int c[];
int dir[][]={{-,},{,},{,-},{,}};
char path[]={'u','d','l','r'};
char op[],input[];
int ans;
stack<int>S; struct Node
{
int s,p;
Node(){}
Node(int S,int P){s=S,p=P;}
}; struct Path
{
int from,dir;
}pa[];
bool f[]; int getnum()
{
int res=;
for(int i=;t[i];i++)
for(int j=i+;t[j];j++)
if(t[j]<t[i]) res=res+c[-i];
return res;
} void getstr(int val)
{
int tmp[],flag[];
memset(flag,,sizeof flag);
for(int i=;i<;i++) tmp[i]=val/c[-i],val=val%c[-i];
for(int i=;i<;i++)
{
int num=;
for(int j=;j<;j++)
{
if(flag[j]==) num++;
if(num==tmp[i]+)
{
t[i]=j+''+; if(t[i]=='') t[i]='x';
flag[j]=;break;
}
}
}
} void bfs(int val,int Pos)
{
queue<Node>Q;
Q.push(Node(val,Pos));
f[val]=; pa[val].from=-,pa[val].dir=-; while(!Q.empty())
{
Node h=Q.front(); Q.pop(); if(h.s==)
{
ans=;
int now=h.s;
while()
{
if(pa[now].from==-) break;
S.push(pa[now].dir);
now=pa[now].from;
}
break;
} int a=h.p/, b=h.p%; getstr(h.s); for(int i=;i<;i++)
{
int x=a+dir[i][],y=b+dir[i][];
if(!(x>=&&x<=&&y>=&&y<=)) continue;
int newpos=*x+y;
swap(t[newpos],t[h.p]);
int news=getnum();
if(f[news]) {swap(t[newpos],t[h.p]);continue;}
pa[news].from=h.s, pa[news].dir=i, f[news]=;
Q.push(Node(news,newpos));
swap(t[newpos],t[h.p]);
}
}
} int main()
{
c[]=; for(int i=;i<=;i++) c[i]=c[i-]*i;
while(~scanf("%s",op))
{
t[]=op[];
int pos;
for(int i=;i<=;i++)
{
scanf("%s",op); t[i]=op[];
if(t[i]=='x') pos=i;
}
int state=getnum(); int sum=;
for(int i=;t[i];i++)
{
if(t[i]=='x') continue;
for(int j=;j<i;j++)
{
if(t[j]=='x') continue;
if(t[i]<t[j]) sum++;
}
} if(sum%==) { printf("unsolvable\n"); continue; } ans=;
memset(f,,sizeof f);
bfs(state,pos); while(!S.empty())
{
printf("%c",path[S.top()]);
S.pop();
}
printf("\n"); }
return ;
}

境界三、广搜+哈希+打表(HDU 263ms,POJ 579ms)

从最终状态(0)开始进行BFS。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std; char t[];
int c[];
int dir[][]={{-,},{,},{,-},{,}};
char path[]={'d','u','r','l'};
char op[],input[]; struct Node
{
int s,p;
Node(){}
Node(int S,int P){s=S,p=P;}
}; struct Path
{
int from,dir;
}pa[];
bool f[]; int getnum()
{
int res=;
for(int i=;t[i];i++)
for(int j=i+;t[j];j++)
if(t[j]<t[i]) res=res+c[-i];
return res;
} void getstr(int val)
{
int tmp[],flag[];
memset(flag,,sizeof flag);
for(int i=;i<;i++) tmp[i]=val/c[-i],val=val%c[-i];
for(int i=;i<;i++)
{
int num=;
for(int j=;j<;j++)
{
if(flag[j]==) num++;
if(num==tmp[i]+)
{
t[i]=j+''+; if(t[i]=='') t[i]='x';
flag[j]=;break;
}
}
}
} void pre()
{
queue<Node>Q;
Q.push(Node(,));
f[]=; pa[].from=-,pa[].dir=-; while(!Q.empty())
{
Node h=Q.front(); Q.pop();
int a=h.p/, b=h.p%; getstr(h.s);
for(int i=;i<;i++)
{
int x=a+dir[i][],y=b+dir[i][];
if(!(x>=&&x<=&&y>=&&y<=)) continue;
int newpos=*x+y;
swap(t[newpos],t[h.p]);
int news=getnum();
if(f[news]) {swap(t[newpos],t[h.p]);continue;}
pa[news].from=h.s, pa[news].dir=i, f[news]=;
Q.push(Node(news,newpos));
swap(t[newpos],t[h.p]);
}
}
} int main()
{
c[]=; for(int i=;i<=;i++) c[i]=c[i-]*i;
pre(); while(~scanf("%s",op))
{
t[]=op[];
for(int i=;i<=;i++) {scanf("%s",op); t[i]=op[];}
int state=getnum();
if(f[state]==) printf("unsolvable\n");
else
{
while()
{
if(pa[state].from==-) break;
printf("%c",path[pa[state].dir]);
state=pa[state].from;
}
printf("\n");
}
}
return ;
}

境界四、双向广搜+哈希(HDU 2636ms, POJ 32ms)

从起点和终点同时开始搜,当某个状态被两个方向的搜索同时搜过时,搜索结束,输出路径。

HDU 不加无解判断剪枝会超时。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std; char input[],t[],op[];
int c[];
struct Node
{
int s,p;
Node(){}
Node(int S,int P){s=S,p=P;}
};
struct Path
{
int from,dir;
}path[];
int f[]; int dir[][] = { { -, },{ , },{ ,- },{ , } };
string d[] = {"","udlr","durl"}; queue<Node>q[];
int ans; stack<int>S;
queue<int>Q; int getnum()
{
int res=;
for(int i=;t[i];i++)
for(int j=i+;t[j];j++)
if(t[j]<t[i]) res=res+c[-i];
return res;
} void getstr(int val)
{
int tmp[],flag[];
memset(flag,,sizeof flag);
for(int i=;i<;i++) tmp[i]=val/c[-i],val=val%c[-i];
for(int i=;i<;i++)
{
int num=;
for(int j=;j<;j++)
{
if(flag[j]==) num++;
if(num==tmp[i]+)
{
t[i]=j+''+; if(t[i]=='') t[i]='x';
flag[j]=;break;
}
}
}
} bool g(int a, int b)
{
if (a >= && a <= && b >= && b <= ) return ;
return ;
} void bfs(int now)
{
Node h=q[now].front(); q[now].pop();
int a=h.p/,b=h.p%;
getstr(h.s); for(int i=;i<;i++)
{
int x=a+dir[i][],y=b+dir[i][];
if(!g(x,y)) continue;
int pos = * x + y; swap(t[h.p],t[pos]); if(f[getnum()]==now) { swap(t[h.p],t[pos]); continue; }
else if(f[getnum()]!=)
{
ans=;
if(now==)
{
S.push(i);
int u=h.s;
while(path[u].from!=-) { S.push(path[u].dir); u=path[u].from; }
u=getnum();
while(path[u].from!=-) { Q.push(path[u].dir); u=path[u].from; }
}
else
{
Q.push(i);
int u=h.s;
while(path[u].from!=-) { Q.push(path[u].dir); u=path[u].from; }
u=getnum();
while(path[u].from!=-) { S.push(path[u].dir); u=path[u].from; }
}
break;
}
else
{
f[getnum()]=now;
path[getnum()].from=h.s;
path[getnum()].dir=i;
q[now].push(Node(getnum(),pos));
swap(t[h.p],t[pos]);
}
}
} void read()
{
t[]=op[];
for(int i=;i<=;i++)
{scanf("%s",op); t[i]=op[];}
for(int i=;i<=;i++) input[i]=t[i];
} void init()
{
memset(f,ans=,sizeof f);
while(!q[].empty()) q[].pop();
while(!q[].empty()) q[].pop();
} void work(int s,int pos)
{
q[].push(Node(s,pos)); q[].push(Node(,));
f[s]=; path[s].from=path[s].dir=-;
f[]=; path[].from=path[].dir=-;
while((!q[].empty())&&(!q[].empty()))
{
if(ans==) break;
bfs(); if(ans==) break;
bfs(); if(ans==) break;
}
} int main()
{
c[]=; for(int i=;i<=;i++) c[i]=c[i-]*i;
while(~scanf("%s",op))
{
read(); int sum=;
for(int i=;t[i];i++)
{
if(t[i]=='x') continue;
for(int j=;j<i;j++)
{
if(t[j]=='x') continue;
if(t[i]<t[j]) sum++;
}
} if(sum%==)
{
printf("unsolvable\n");
continue;
}
init();
for(int i=;i<;i++)
if(input[i]=='x'){work(getnum(),i); break; }
if(ans==)
{
while(!S.empty()) { printf("%c",d[][S.top()]); S.pop(); }
while(!Q.empty()) { printf("%c",d[][Q.front()]); Q.pop(); }
}
else printf("unsolvable");
printf("\n");
}
return ;
}

境界五、A*+哈希+简单估价函数(POJ 391ms)

之后的境界采用最小堆优化,这里我直接用了,f小的先取

试了一下用普通队列的,G++跑了680ms左右,C++TLE(主要原因是写法不好,我常数写的有点大了)。显然最小堆优化在效率上有极大的提高。

g(n)是深度,即从初始到目前的操作次数,h(n)是简单估价函数,表示目前状态与最终状态同一位置不同数字的个数。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std; char input[],t[],op[];
int c[];
struct Node
{
int s,p;
int f,g,h;
Node(){}
Node(int S,int P,int G,int H)
{
s=S,p=P;
g=G,h=H;
f=g+h;
}
bool operator < (const Node &a) const {
return f>a.f;
}
}; struct Path
{
int from,dir;
}path[];
int flag[];
int G[]; int dir[][] = { { -, },{ , },{ ,- },{ , } };
string d = "udlr"; priority_queue<Node>Q;
int ans; stack<int>S; int getnum()
{
int res=;
for(int i=;t[i];i++)
for(int j=i+;t[j];j++)
if(t[j]<t[i]) res=res+c[-i];
return res;
} void getstr(int val)
{
int tmp[],flag[];
memset(flag,,sizeof flag);
for(int i=;i<;i++) tmp[i]=val/c[-i],val=val%c[-i];
for(int i=;i<;i++)
{
int num=;
for(int j=;j<;j++)
{
if(flag[j]==) num++;
if(num==tmp[i]+)
{
t[i]=j+''+; if(t[i]=='') t[i]='x';
flag[j]=;break;
}
}
}
} bool g(int a, int b)
{
if (a>= && a<= && b>= && b<=) return ;
return ;
} void read()
{
t[]=op[];
for(int i=;i<=;i++) {scanf("%s",op); t[i]=op[];}
for(int i=;i<=;i++) input[i]=t[i];
} void init()
{
memset(G,-,sizeof G);
memset(flag,,sizeof flag);
while(!Q.empty()) Q.pop();
} int H(int val)
{
char tmp[];
for(int i=;i<=;i++) tmp[i]=t[i]; getstr(val); int res=;
for(int i=;i<;i++)
{
if(i<) if(t[i]-''!=i+) res++;
if(i==&&t[i]!='x') res++;
} for(int i=;i<=;i++) t[i]=tmp[i];
return res;
} void A_star(int s,int pos)
{
flag[s]=; G[s]=;
path[s].from=-;
path[s].dir=-;
Q.push(Node(s,pos,,H(s)));
while(!Q.empty())
{
Node h=Q.top(); Q.pop(); flag[h.s]=;
getstr(h.s);
if(h.s==)
{
ans=; int now=h.s;
while()
{
if(path[now].from==-) return;
S.push(path[now].dir);
now=path[now].from;
}
} int a=h.p/,b=h.p%; for(int i=;i<;i++)
{
int x=a+dir[i][],y=b+dir[i][];
if(!g(x,y)) continue;
int newpos=*x+y; swap(t[h.p],t[newpos]);
int news=getnum();
swap(t[h.p],t[newpos]); if(flag[news]==||(flag[news]==&&h.g+<G[news]))
{
flag[news]=; G[news]=h.g+;
path[news].from=h.s;
path[news].dir=i;
Q.push(Node(news,newpos,h.g+,H(news)));
}
}
}
} int main()
{
c[]=; for(int i=;i<=;i++) c[i]=c[i-]*i;
while(~scanf("%s",op))
{
read();
int sum=;
for(int i=;t[i];i++)
{
if(t[i]=='x') continue;
for(int j=;j<i;j++)
{
if(t[j]=='x') continue;
if(t[i]<t[j]) sum++;
}
} if(sum%==)
{
printf("unsolvable\n");
continue;
}
init(); for(int i=;i<;i++)
if(input[i]=='x'){A_star(getnum(),i); break; }
while(!S.empty()){printf("%c",d[S.top()]); S.pop();}
printf("\n");
}
return ;
}

境界六、A*+哈希+曼哈顿距离 (POJ 735ms)

与境界5唯一不同的是 估价函数h()。这里估价函数采用曼哈顿距离。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std; char input[],t[],op[];
int c[];
struct Node
{
int s,p;
int f,g,h;
Node(){}
Node(int S,int P,int G,int H)
{
s=S,p=P;
g=G,h=H;
f=g+h;
}
}; struct Path
{
int from,dir;
}path[];
int flag[];
int G[]; int dir[][] = { { -, },{ , },{ ,- },{ , } };
string d = "udlr"; queue<Node>Q;
int ans; stack<int>S; int getnum()
{
int res=;
for(int i=;t[i];i++)
for(int j=i+;t[j];j++)
if(t[j]<t[i]) res=res+c[-i];
return res;
} void getstr(int val)
{
int tmp[],flag[];
memset(flag,,sizeof flag);
for(int i=;i<;i++) tmp[i]=val/c[-i],val=val%c[-i];
for(int i=;i<;i++)
{
int num=;
for(int j=;j<;j++)
{
if(flag[j]==) num++;
if(num==tmp[i]+)
{
t[i]=j+''+; if(t[i]=='') t[i]='x';
flag[j]=;break;
}
}
}
} bool g(int a, int b)
{
if (a>= && a<= && b>= && b<=) return ;
return ;
} void read()
{
t[]=op[];
for(int i=;i<=;i++) {scanf("%s",op); t[i]=op[];}
for(int i=;i<=;i++) input[i]=t[i];
} void init()
{
memset(G,-,sizeof G);
memset(flag,,sizeof flag);
while(!Q.empty()) Q.pop();
} int H(int val)
{
char tmp[];
for(int i=;i<=;i++) tmp[i]=t[i]; getstr(val); int res=; for(int i=;i<;i++)
{
if(t[i]=='x') continue; int num=t[i]-''-;
int a=i/,b=i%;
int x=num/,y=num%; res=res+abs(a-x)+abs(b-y);
} for(int i=;i<=;i++) t[i]=tmp[i];
return res;
} void A_star(int s,int pos)
{
flag[s]=; G[s]=;
path[s].from=-;
path[s].dir=-;
Q.push(Node(s,pos,,H(s)));
while(!Q.empty())
{
Node h=Q.front(); Q.pop(); flag[h.s]=;
getstr(h.s);
if(h.s==)
{
ans=; int now=h.s;
while()
{
if(path[now].from==-) return;
S.push(path[now].dir);
now=path[now].from;
}
} int a=h.p/,b=h.p%; for(int i=;i<;i++)
{
int x=a+dir[i][],y=b+dir[i][];
if(!g(x,y)) continue;
int newpos=*x+y; swap(t[h.p],t[newpos]);
int news=getnum();
swap(t[h.p],t[newpos]); if(flag[news]==||(flag[news]==&&h.g+<G[news]))
{
flag[news]=; G[news]=h.g+;
path[news].from=h.s;
path[news].dir=i;
Q.push(Node(news,newpos,h.g+,H(news)));
}
}
}
} int main()
{
c[]=; for(int i=;i<=;i++) c[i]=c[i-]*i;
while(~scanf("%s",op))
{
read();
int sum=;
for(int i=;t[i];i++)
{
if(t[i]=='x') continue;
for(int j=;j<i;j++)
{
if(t[j]=='x') continue;
if(t[i]<t[j]) sum++;
}
} if(sum%==)
{
printf("unsolvable\n");
continue;
}
init();
for(int i=;i<;i++)
if(input[i]=='x'){A_star(getnum(),i); break; } while(!S.empty()){printf("%c",d[S.top()]); S.pop();}
printf("\n");
}
return ;
}

境界七、A*+哈希+曼哈顿距离+小顶堆 (HDU 1404ms,POJ 16ms)

境界六加上最小堆优化,这个优化的效率改进是巨大的!!!!

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std; char input[],t[],op[];
int c[];
struct Node
{
int s,p;
int f,g,h;
Node(){}
Node(int S,int P,int G,int H)
{
s=S,p=P;
g=G,h=H;
f=g+h;
}
bool operator < (const Node &a) const {
return f>a.f;
}
}; struct Path
{
int from,dir;
}path[];
int flag[];
int G[]; int dir[][] = { { -, },{ , },{ ,- },{ , } };
string d = "udlr"; priority_queue<Node>Q;
int ans; stack<int>S; int getnum()
{
int res=;
for(int i=;t[i];i++)
for(int j=i+;t[j];j++)
if(t[j]<t[i]) res=res+c[-i];
return res;
} void getstr(int val)
{
int tmp[],flag[];
memset(flag,,sizeof flag);
for(int i=;i<;i++) tmp[i]=val/c[-i],val=val%c[-i];
for(int i=;i<;i++)
{
int num=;
for(int j=;j<;j++)
{
if(flag[j]==) num++;
if(num==tmp[i]+)
{
t[i]=j+''+; if(t[i]=='') t[i]='x';
flag[j]=;break;
}
}
}
} bool g(int a, int b)
{
if (a>= && a<= && b>= && b<=) return ;
return ;
} void read()
{
t[]=op[];
for(int i=;i<=;i++) {scanf("%s",op); t[i]=op[];}
for(int i=;i<=;i++) input[i]=t[i];
} void init()
{
memset(G,-,sizeof G);
memset(flag,,sizeof flag);
while(!Q.empty()) Q.pop();
} int H(int val)
{
char tmp[];
for(int i=;i<=;i++) tmp[i]=t[i]; getstr(val); int res=; for(int i=;i<;i++)
{
if(t[i]=='x') continue; int num=t[i]-''-;
int a=i/,b=i%;
int x=num/,y=num%; res=res+abs(a-x)+abs(b-y);
} for(int i=;i<=;i++) t[i]=tmp[i];
return res;
} void A_star(int s,int pos)
{
flag[s]=; G[s]=;
path[s].from=-;
path[s].dir=-;
Q.push(Node(s,pos,,H(s)));
while(!Q.empty())
{
Node h=Q.top(); Q.pop(); flag[h.s]=;
getstr(h.s);
if(h.s==)
{
ans=; int now=h.s;
while()
{
if(path[now].from==-) return;
S.push(path[now].dir);
now=path[now].from;
}
} int a=h.p/,b=h.p%; for(int i=;i<;i++)
{
int x=a+dir[i][],y=b+dir[i][];
if(!g(x,y)) continue;
int newpos=*x+y; swap(t[h.p],t[newpos]);
int news=getnum();
swap(t[h.p],t[newpos]); if(flag[news]==||(flag[news]==&&h.g+<G[news]))
{
flag[news]=; G[news]=h.g+;
path[news].from=h.s;
path[news].dir=i;
Q.push(Node(news,newpos,h.g+,H(news)));
}
}
}
} int main()
{
c[]=; for(int i=;i<=;i++) c[i]=c[i-]*i;
while(~scanf("%s",op))
{
read();
int sum=;
for(int i=;t[i];i++)
{
if(t[i]=='x') continue;
for(int j=;j<i;j++)
{
if(t[j]=='x') continue;
if(t[i]<t[j]) sum++;
}
} if(sum%==)
{
printf("unsolvable\n");
continue;
}
init();
for(int i=;i<;i++)
if(input[i]=='x'){A_star(getnum(),i); break; } while(!S.empty()){printf("%c",d[S.top()]); S.pop();}
printf("\n");
}
return ;
}

境界八、IDA*+曼哈顿距离(HDU 2106ms,POJ 79ms)

采用迭代深搜的思想,利用A*估价函数剪枝。

第一次允许搜索到的深度为limit,如果有解,直接输出。

在最大值深度为limit的情况下,如果无解,则将limit++,继续从头开始搜索。直到搜到解。

剪枝:if(deep+h(s)>limit) return; deep表示这一次搜索达到此状态的操作次数,h(s)为估价函数。

IDA*策略占用空间极小,一般情况下效率会比A*高。

至于为什么我的IDA*比A*慢.....估计我这种写法常数太大了吧......

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std; char input[],t[],op[];
int c[];
int dir[][] = { { -, },{ , },{ ,- },{ , } };
string d = "udlr";
int flag,limit,length;
int path[]; int getnum()
{
int res=;
for(int i=;t[i];i++)
for(int j=i+;t[j];j++)
if(t[j]<t[i]) res=res+c[-i];
return res;
} void getstr(int val)
{
int tmp[],flag[];
memset(flag,,sizeof flag);
for(int i=;i<;i++) tmp[i]=val/c[-i],val=val%c[-i];
for(int i=;i<;i++)
{
int num=;
for(int j=;j<;j++)
{
if(flag[j]==) num++;
if(num==tmp[i]+)
{
t[i]=j+''+; if(t[i]=='') t[i]='x';
flag[j]=;break;
}
}
}
} bool g(int a, int b)
{
if (a>= && a<= && b>= && b<=) return ;
return ;
} void read()
{
t[]=op[];
for(int i=;i<=;i++) {scanf("%s",op); t[i]=op[];}
for(int i=;i<=;i++) input[i]=t[i];
} int H(int val)
{
char tmp[];
for(int i=;i<=;i++) tmp[i]=t[i];
getstr(val); int res=; for(int i=;i<;i++)
{
if(t[i]=='x') continue; int num=t[i]-''-;
int a=i/,b=i%;
int x=num/,y=num%;
res=res+abs(a-x)+abs(b-y);
} for(int i=;i<=;i++) t[i]=tmp[i];
return res;
} void dfs(int pos,int s,int deep,int pre_dir)
{
if(s==)
{
length=deep;
flag=;return;
}
if(deep+H(s)>limit) return; char u[]; getstr(s);
for(int i=;i<=;i++) u[i]=t[i]; int a=pos/,b=pos%;
for(int i=;i<;i++)
{
if(pre_dir==&&i==) continue;
if(pre_dir==&&i==) continue;
if(pre_dir==&&i==) continue;
if(pre_dir==&&i==) continue; int x=a+dir[i][],y=b+dir[i][];
if(!g(x,y)) continue; int new_pos=*x+y; swap(u[pos],u[new_pos]); for(int i=;i<=;i++) t[i]=u[i];
int new_s=getnum(); path[deep]=i;
dfs(new_pos,new_s,deep+,i); if(flag) return;
swap(u[pos],u[new_pos]);
} } int main()
{
c[]=; for(int i=;i<=;i++) c[i]=c[i-]*i;
while(~scanf("%s",op))
{
read(); int sum=;
for(int i=;t[i];i++)
{
if(t[i]=='x') continue;
for(int j=;j<i;j++)
{
if(t[j]=='x') continue;
if(t[i]<t[j]) sum++;
}
} if(sum%==) { printf("unsolvable\n"); continue; } for(int i=;i<;i++)
{
if(input[i]!='x') continue;
limit=H(getnum()); flag=;
while(!flag)
{
for(int i=;i<=;i++) t[i]=input[i]; int ggg=getnum();
dfs(i,ggg,,-); if(flag) break;
limit++;
} for(int i=;i<limit;i++) printf("%c",d[path[i]]);
printf("\n");
}
}
return ;
}

HDU 1043 八数码(八境界)的更多相关文章

  1. HDU 1043 Eight(八数码)

    HDU 1043 Eight(八数码) 00 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)   Problem Descr ...

  2. hdu 1043 Eight 经典八数码问题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 The 15-puzzle has been around for over 100 years ...

  3. HDU 1043

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 http://www.cnblogs.com/goodness/archive/2010/05/04/17 ...

  4. Hdu 1043 Eight (八数码问题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目描述: 3*3的格子,填有1到8,8个数字,还有一个x,x可以上下左右移动,问最终能否移动 ...

  5. Eight POJ - 1077 HDU - 1043 八数码

    Eight POJ - 1077 HDU - 1043 八数码问题.用hash(康托展开)判重 bfs(TLE) #include<cstdio> #include<iostream ...

  6. HDU 1043 Eight 八数码问题 A*算法(经典问题)

    HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...

  7. HDU 1043 Eight (BFS&#183;八数码&#183;康托展开)

    题意  输出八数码问题从给定状态到12345678x的路径 用康托展开将排列相应为整数  即这个排列在全部排列中的字典序  然后就是基础的BFS了 #include <bits/stdc++.h ...

  8. HDU 1043 八数码(A*搜索)

    在学习八数码A*搜索问题的时候须要知道下面几个点: Hash:利用康托展开进行hash 康托展开主要就是依据一个序列求这个序列是第几大的序列. A*搜索:这里的启示函数就用两点之间的曼哈顿距离进行计算 ...

  9. HDU 3567 Eight II(八数码 II)

    HDU 3567 Eight II(八数码 II) /65536 K (Java/Others)   Problem Description - 题目描述 Eight-puzzle, which is ...

  10. HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法

    先是这周是搜索的题,网站:http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6041 主要内容是BFS,A*,IDA*,还有一道K短路的,.. ...

随机推荐

  1. 水电pd建表

    drop table ADMINSTER cascade constraints; /========================================================= ...

  2. 使用HttpClient工具类测试Http接口

    一.httpClient模拟客户端 import java.util.ArrayList;import java.util.Iterator;import java.util.List;import ...

  3. 学习multiprocessing

    1. multiprocessing.Pool from multiprocessing.pool import Pool def gen_row(): ...return rows def main ...

  4. android应用的优化建议(转载)

    首先,这是我在http://www.oschina.net/translate/40-developer-tips-for-android-optimization看到的一片文章,感觉挺有道理的,所以 ...

  5. UESTC 1217 The Battle of Chibi

    dp+树状数组优化. dp[i][j]表示以a[i]结尾,最长上升序列长度为j的方案数.dp[i][j]=sum{dp[k][j-1]} 其中k<i&&a[k]<a[i]. ...

  6. URL scheme添加以及查找方式

    2.1.1  添加URL Types URL Scheme是通过系统找到并跳转对应app的一类设置,通过向项目中的info.plist文件中加入URL types可使用第三方平台所注册的appkey信 ...

  7. VMware 虚拟机(linux)增加根目录磁盘空间

    今天查看学校的监控报修系统,不能访问了!!!系统运行很慢,用top命令查看发现内存使用率90%,用"df -h ”查看“/”目录使用率已达到80%,导致系统运行很慢.我用以下方法扩大根目录磁 ...

  8. html元素中class属性值多个空格分格是什么意思?

    即指定多个class,这是bootstrap常干的事,比如 <div class="alert alert-info"> 请问,这两个class之间的关系是什么,二者的 ...

  9. JavaScript在智能手机上的应用-测试是否支持滑动事件

    ---------------------------- <script type="text/javascript">                        ...

  10. IntelliJ IDEA 7.0 正式版注册机代码

    好神奇,第一次看见注册机的源代码,自己运行一下.可以是java IDE环境,也可以是配置好jdk的dos环境. 然后输入自己的用户名就可以获得相对应的注册码,输入到软件中即可. 仅供参考,请购买正版. ...