您的位置:首页 > 其它

POJ1077——Eight

2016-08-06 10:51 281 查看
3 * 3的矩阵的八数码问题。比较简单

因为输入的只是1-8,所以可以将x当作9.

解决问题的关键是将数字序列根据康托展开转换成一个数,每一个数对应一个序列,所以可以用来判断这个序列是否查找过。

用深搜搜索,总共9!种,还可以接受。

下面是代码:

#include <iostream>
#include <queue>
using namespace std;

const int SIZE = 362880; //数组最大值
int fac[] = {1,1,2,6,24,120,720,5040,40320,362880}; //0 - 9的阶乘

int xy[4][2] = {-1,0,1,0,0,-1,0,1}; //四个方向搜索
int parent[SIZE]; //查找路径需要的父节点的数组
char visited[SIZE]; //判断是否查找过
char move[SIZE]; //记录某个序列向哪个方向移动

struct node //节点,包括了序列,空格的位置x,以及序列根据康托展开转成的数
{
char str[9];
char x;
int kangtuo;
};

int kangtuo(char *s, int n) //康托展开把一个序列转成一个数
{
int i, j, temp, num;
num = 0;
for(i = 0; i < n - 1; i++)
{
temp = 0;
for(j = i + 1; j < n; j++)
{
if(s[j] < s[i])
temp++;
}
num += fac[s[i] - 1] * temp;
}
return num;
}

int hash(char *cur)
{
return kangtuo(cur, 9);
}

void bfs(node &start) //深搜
{
int x, y, k, a, b;
int u, v;

for(k = 0; k < SIZE; ++k) //初始化visited
visited[k] = 0;

u = start.kangtuo; //第一个序列的康托数

parent[u] = -1; //父节点为-1
visited[u] = 1; //标记为查找过
queue<node> que;
que.push(start); //入队

node temp, te;
while(!que.empty())
{
te = que.front();
que.pop();
u = te.kangtuo;
k = te.x; //根据x的下标,找到x的坐标
x = k / 3;
y = k % 3;

for(int i = 0; i < 4; i++) //四个方向进行交换
{
a = x + xy[i][0];
b = y + xy[i][1];
if(0 <= a && a <= 2 && 0 <= b && b <= 2) //符合条件的交换位置,计算康托数,判断是否查找过,
{
temp = te;
temp.x = a * 3 + b;
swap(temp.str[k], temp.str[temp.x]);
temp.kangtuo = hash(temp.str);
v = temp.kangtuo;
if(visited[v] != 1)
{
move[v] = i;
visited[v] = 1;
parent[v] = u;
if(v == 0) //判断是否查找完成,是则返回,不是添加如队
return;
que.push(temp);
}
}
}
}
}

void print_path() //根据parent数组和move数组找出路径
{
int n, u;
char path[1000];
n = 1;
path[0] = move[0];
u = parent[0];
while(parent[u] != -1)
{
path
= move[u];
++n;
u = parent[u];
}

for(int i = n - 1; i >= 0; --i)
{
if(path[i] == 0)
cout << "u";
else if(path[i] == 1)
cout << "d";
else if(path[i] == 2)
cout << "l";
else
cout << "r";
}
}

int main()
{
node start;
char c;
for(int i = 0; i < 9; i++)
{
cin >> c;
if(c == 'x')
{
start.str[i] = 9;
start.x = i;
}
else
start.str[i] = c - '0';
}
start.kangtuo = hash(start.str);
bfs(start);

if(visited[0] == 1)
{
print_path();
cout << endl;
}
else
cout << "unsolvable" << endl;

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj 搜索