这是一个八数码问题,正好学习了康托展开,就做了这题,和hdu1043很像。
康托展开并不难理解,其实就是一种hash。先上模板方便以后自己看。
康托展开:
int Contor(int str[],int n)
{
int ans = 0;
for(int i = 0; i < n; i++)
{
int cnt = 0;
for(int j = i+1; j < n; j++)
{
if(str[i]>str[j])
cnt++;
}
ans += cnt*f[n-i-1];
}
return ans+1;
}
逆康托展开:
void unContor(char res[], int x, int n) //第x大数字序列(从0开始),1-n排列
{
int i, j;
int cnt;
bool visited[100];
for(i = n-1; i >= 0; i--)
{
int consult = x/factory[i]; //每一项的系数
x -= consult*factory[i]; //余数
for(j = 0, cnt = 0; cnt <= consult; j++)
{
if(!visited[j+1]) //未被使用的数字中,第consult大的数字
cnt++;
}
visited[j] = true; //标记第consult大的已经被使用
res[n-1-i] = j+'0';
}
}
本题用康托展开的hash值来记录状态,用bfs进行搜索
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>
#include <string>
using namespace std;
typedef long long ll;
const int maxn = 363000; //最多就9!种
int f[10];
int vis[maxn];
string path;
int dict[4][2] = {-1,0,0,1,1,0,0,-1};
char idx[5] = "urdl";
struct node
{
int s[9];
int loc; //位置
int status;//hash值
string path;
} a;
void init()
{
f[0] = 0;
f[1] = 1;
for(int i = 2; i <= 9; i++)
{
f[i] = f[i-1]*i;
}
}
int Contor(int str[],int n)
{
int ans = 0;
for(int i = 0; i < n; i++)
{
int cnt = 0;
for(int j = i+1; j < n; j++)
{
if(str[i]>str[j])
cnt++;
}
ans += cnt*f[n-i-1];
}
return ans+1;
}
bool bfs()
{
memset(vis,0,sizeof(vis));
node cur,next;
queue<node>q;
q.push(a);
while(!q.empty())
{
cur = q.front();
q.pop();
if(cur.status==46234) //123456780康托展开的hash值
{
path = cur.path;
return true;
}
int x = cur.loc/3;
int y = cur.loc%3;
for(int i = 0; i < 4; i++)
{
int dx = x + dict[i][0];
int dy = y + dict[i][1];
if(dx<0||dx>2||dy<0||dy>2) continue;
next = cur;
next.loc = dx*3+dy;
next.s[cur.loc] = next.s[next.loc];
next.s[next.loc] = 0;
next.status = Contor(next.s,9);
if(!vis[next.status])
{
vis[next.status] = 1;
next.path = next.path + idx[i];
q.push(next);
}
}
}
return false;
}
int main()
{
init();
char c;
for(int i = 0; i < 9; i++)
{
cin >> c;
if(c=='x')
{
a.s[i] = 0;
a.loc = i;
}
else
a.s[i] = c-'0';
}
a.status = Contor(a.s,9);
if(bfs())
cout<<path<<endl;
else
cout<<"unsolvable"<<endl;
return 0;
}