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;
}
因为输入的只是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 1077 Eight(据说此题不做人生不完整~~~)
- POJ 1077 - Eight(BFS+康托展开)
- poj 1077 Eight A*解八数码问题
- poj 1077-Eight;hdu 1043-Eight
- POJ - 1077 Eight
- POJ 1077 Eight 八数码+A* -
- POJ 1077 Eight BFS -
- poj - 1077 - Eight
- poj 1077-Eight(八数码+逆向bfs打表)
- poj 1077 Eight(经典八数码问题:bfs/Dbfs)
- POJ 1077 Eight
- POJ 1077 Eight 八数码问题 A*
- POJ 1077 Eight
- 搜索 ( 八数码问题详解:BFS,A*,IDA* )——Eight ( POJ 1077 )
- HDU 1043 && POJ 1077 Eight bfs || 双向bfs || A*搜索
- [POJ]1077 Eight 八数码:康托展开+BFS
- HDU 1043 Eight(经典八数码问题)对比POJ 1077
- poj 1077 Eight
- poj 1077 Eight 八数码 A*算法
- POJ 1077 Eight(BFS八数码问题)