传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1043
题目大意:经典的八数码问题,给定状态,求移回原始按顺序的序列的操作序列。
思路:从状态”12345678x“开始BFS下去,逐渐扩展,遍历所有可能得到的状态,顺便记录每个状态结点的父子关系,为后面输出操作序列作准备,判重为了方便,用了一个效率不太好的STL map,搞了点伪哈希,把9!个状态映射成从1到9!的9!个数字作为判重的基数,剩下的就是码的功夫了,在时间要求不太高(2s内),空间允许(28~30M左右)的情况下可以有效的得出解。
另外:网上还有其他更优的解法,使用真正的哈希方法,还有双向广搜加快速的,A*,IDA*的一类启发式合并搜索解法,会达到更快的速度,由于目前还没理解启发式合并的真正的内涵,只能写出广搜加上哈希的解法,还有一种就是充满恶意猥琐的打表。
Code:
/* W w w mm mm 222222222 7777777777777 */
/* W w w w m m m m 222 22 7777 */
/* w w w w m m m m 22 777 */
/* w w w w m m m m 22 77 */
/* w w w w m m m m 222 77 */
/* w w w w m m m m 222 77 */
/* w w w w m m m m 222 77 */
/* w w w w m m m m 222 77 */
/* w w w w m m m m 222 77 */
/* ww ww m mm m 222222222222222 77 */
//#pragma comment(linker, "/STACK:102400000,102400000")
//C++
//int size = 256 << 20; // 256MB
//char *p = (char*)malloc(size) + size;
//__asm__("movl %0, %%esp\n" :: "r"(p));
//G++
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<ctime>
#include<deque>
#include<cmath>
#include<vector>
#include<string>
#include<cctype>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
#define REP(i,s,t) for(int i=(s);i<=(t);i++)
#define REP2(i,t,s) for(int i=(t);i>=s;i--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned long ul;
const int MS=370000;
const int N=12;
char s[N],st[N],en[N];
map<string,int>M;
//map<int,string>M2;
int cnt;
int fa[MS],op[MS];
int dx[5]= {0,0,-1,1};
int dy[5]= {-1,1,0,0};
bool vis[MS];
queue<string>Q;
vector<char>ans;
void Hashinit()
{
M.clear();
//M2.clear();
REP(i,0,8)
{
s[i]=i+1+'0';
}
s[9]=0;
cnt=0;
do
{
M[s]=++cnt;
//M2[cnt]=s;
}
while(next_permutation(s,s+9));
}
void fuck()
{
REP(i,0,8)
{
st[i]=i+1+'0';
}
st[9]=0;
memset(vis,false,sizeof(vis));
memset(fa,-1,sizeof(fa));
memset(op,-1,sizeof(op));
vis[M[st]]=1;
while(!Q.empty())
{
Q.pop();
}
Q.push(st);
while(!Q.empty())
{
string tp=Q.front();
Q.pop();
int f=M[tp];
int pos;
REP(i,0,8)
{
if(tp[i]=='9')
{
pos=i;
break;
}
}
int cx=pos/3,cy=pos%3;
int nx,ny;
REP(i,0,3)
{
nx=cx+dx[i];
ny=cy+dy[i];
if(nx>=0&&nx<=2&&ny>=0&&ny<=2)
{
swap(tp[pos],tp[nx*3+ny]);
int x=M[tp];
if(!vis[x])
{
Q.push(tp);
fa[x]=f;
op[x]=i;
vis[x]=1;
}
swap(tp[pos],tp[nx*3+ny]);
}
}
}
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("test.in","r",stdin);
#endif
Hashinit();
fuck();
while(~scanf(" %c",&st[0]))
{
if(st[0]=='x')
{
st[0]='9';
}
REP(i,1,8)
{
scanf(" %c",&st[i]);
if(st[i]=='x')
{
st[i]='9';
}
}
st[9]=0;
if(!vis[M[st]])
{
puts("unsolvable");
continue;
}
ans.clear();
int xx=M[st];
while(fa[xx]!=-1)
{
char tmp;
if(op[xx]==0||op[xx]==1)
{
tmp=(op[xx]==1?'l':'r');
ans.push_back(tmp);
}
if(op[xx]==2||op[xx]==3)
{
tmp=(op[xx]==3?'u':'d');
ans.push_back(tmp);
}
//cout<<M2[xx]<<endl;
xx=fa[xx];
}
for(int i=0; i<ans.size(); i++)
{
printf("%c",ans[i]);
}
printf("\n");
}
return 0;
}