pku 1077 Eight
题目地址:http://poj.org/problem?id=1077
题目大意:
经典的八数码问题,给你一个3*3,其中一个数位x的图,问是否能通过移动x,来使图形成为一个
123
456
78x
这样图形,可以的话,输出x 的移动路径,经典的BFS。
详细分析:
这边先点一下,以后详细填坑。
这边的话需要用到康托展开,康拓展开也可以看成一种hash函数,关键是得用一种映射方法,把你当前的搜索状态(我猜是一个图),映射为一个值,便于判断是否搜索过,可以用来减少判重时间的同时还可以避免不必要的搜索
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
using namespace std;
typedef long long ll;
#define aim 1 //目标图形对应的cantor值
struct Node
{
int Map[9];
ll val; //康拓展开对应的值
int x;
};
char s[100];
ll ans[9] ={1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dirc[4][2] = {{1,0},{-1,0},{0,-1},{0,1}};
char opt[4] = {'d', 'u', 'l', 'r'};
int vis[500005];
int pre[500005];
char path[500005];
ll Cantor(Node& t)
{
ll ret = 0;
for(int i = 0 ;i < 9; i++)
{
int cnt = 0;
for(int j = i + 1 ; j < 9 ;j++ )
{
if(t.Map[j] < t.Map[i])
cnt++;
}
ret += cnt* ans[ 8 - i ];
}
return ret + 1;
}
int BFS(Node& T) //找初始点到目标节点的最短路径
{
queue<Node> q;
Node temp , Front ;
temp = T;
vis[temp.val] = 1;
q.push(temp);
while(!q.empty())
{
Front = q.front();
q.pop();
if(Front.val == aim)
{
return 1;
}
for(int i = 0 ;i < 4; i++)
{
temp = Front;
int pos_x = temp.x/3;
int pos_y = temp.x%3;
pos_x += dirc[i][0];
pos_y += dirc[i][1];
if( pos_x>=0 && pos_x <3 && pos_y >=0 && pos_y <3 )
{
swap( temp.Map[pos_x*3 + pos_y], temp.Map[temp.x]);
ll can_val = Cantor(temp);
if(!vis[can_val])
{
temp.val = can_val;
temp.x = pos_x*3 + pos_y;
vis[can_val] = 1;
pre[temp.val] = Front.val;
path[temp.val] = opt[i];
q.push(temp);
}
}
}
}
return 0;
}
void show_path(int i)
{
if(i == 0)
return ;
show_path( pre[i] );
if( pre[i] != 0 )
cout << path[i];
}
int main()
{
Node First;
while(gets(s))
{
memset(vis,0,sizeof(vis));
int index = 0;
for(int i = 0 ;i < strlen(s); i++) //二维数组用一维存储
{
if(s[i] >='1' && s[i] <='8')
First.Map[ index++ ] = s[i] -'0';
else if(s[i] == 'x')
{
First.x = index;
First.Map[index++ ] = 9;
}
}
First.val = Cantor(First) ;
pre[First.val] = 0;
/*
cout << First.val << endl;
cout << First.x << endl;
for(int i = 0 ;i < 9 ;i++)
cout << First.Map[i] << endl;
*/
if( BFS(First) )
{
show_path(1);
cout << endl;
}
else
cout << "unsolvable"<< endl;
// cout << pre[1] << endl;
//cout << "have done" << endl;
}
return 0;
}