poj - 1077 - Eight
2013-05-26 22:13
465 查看
题意:八数码问题,对于给定的初始态,求出到达目标态的路径。
题目链接:http://poj.org/problem?id=1077
——>>上ACM课的,老师讲的例题,看老师的代码看不明白;寒假看白书,轻松AC,今天重刷一次,竟将目标状态写多了一个9,debug了好久。
这也是我所做的第一道哈希题;对于一个八数码图,对应着一个状态,那么总共会有9!个状态,近40万个, 可以将这些状态对应哈希值。那么,可以从一个初始状态开始搜,上、下、左、右地走,每走一次就判断是否已为目标态:
是的话,返回;
不是的话,记录这个状态已走过,下次再有转移到此状态的就不继续做处理了(现已处理);
注意:结点查找表存的是队列的编号而不是状态。
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1000003;
typedef int State[9];
State st[maxn];
int goal[] = {1, 2, 3, 4, 5, 6, 7, 8, 0};
int dx[] = {-1, 1, 0, 0};
int dy[] = { 0, 0, -1, 1};
int head[maxn], nxt[maxn], fa[maxn];
char dir[maxn];
int Hash(State s) //哈希函数
{
int ret = 0, i;
for(i = 0; i < 9; i++) ret = ret * 10 + s[i];
return ret % maxn;
}
bool try_to_insert(int rear) //插入哈希表
{
int h = Hash(st[rear]);
for(int e = head[h]; e != -1; e = nxt[e])
{
if(memcmp(st[e], st[rear], sizeof(st[e])) == 0) return 0;
}
nxt[rear] = head[h];
head[h] = rear;
return 1;
}
int bfs() //遍历
{
int frt = 1, rear = 2, i, z;
while(frt < rear)
{
State& s = st[frt];
if(memcmp(s, goal, sizeof(s)) == 0) return frt;
for(z = 0; s[z] != 0; z++);
int x = z / 3;
int y = z % 3;
for(i = 0; i < 4; i++)
{
int newx = x + dx[i];
int newy = y + dy[i];
int newz = 3 * newx + newy;
if(newx >= 0 && newx < 3 && newy >= 0 && newy < 3)
{
State& news = st[rear];
memcpy(news, s, sizeof(s));
news[z] = s[newz];
news[newz] = 0;
if(try_to_insert(rear))
{
fa[rear] = frt;
switch(i)
{
case 0: dir[rear] = 'u'; break;
case 1: dir[rear] = 'd'; break;
case 2: dir[rear] = 'l'; break;
case 3: dir[rear] = 'r'; break;
default: break;
}
rear++;
}
}
}
frt++;
}
return 0;
}
void print(int i) //输出
{
if(fa[i] == -1) return;
print(fa[i]);
cout<<dir[i];
}
int main()
{
char c[10];
int i, ret;
while(cin>>c[0]>>c[1]>>c[2]>>c[3]>>c[4]>>c[5]>>c[6]>>c[7]>>c[8])
{
for(i = 0; i < 9; i++) st[1][i] = c[i] == 'x' ? 0 : (int)(c[i]-'0');
memset(head, -1, sizeof(head));
fa[1] = -1;
ret = bfs();
if(ret)
{
print(ret);
}
else cout<<"unsolvable";
cout<<endl;
}
return 0;
}
题目链接:http://poj.org/problem?id=1077
——>>上ACM课的,老师讲的例题,看老师的代码看不明白;寒假看白书,轻松AC,今天重刷一次,竟将目标状态写多了一个9,debug了好久。
这也是我所做的第一道哈希题;对于一个八数码图,对应着一个状态,那么总共会有9!个状态,近40万个, 可以将这些状态对应哈希值。那么,可以从一个初始状态开始搜,上、下、左、右地走,每走一次就判断是否已为目标态:
是的话,返回;
不是的话,记录这个状态已走过,下次再有转移到此状态的就不继续做处理了(现已处理);
注意:结点查找表存的是队列的编号而不是状态。
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1000003;
typedef int State[9];
State st[maxn];
int goal[] = {1, 2, 3, 4, 5, 6, 7, 8, 0};
int dx[] = {-1, 1, 0, 0};
int dy[] = { 0, 0, -1, 1};
int head[maxn], nxt[maxn], fa[maxn];
char dir[maxn];
int Hash(State s) //哈希函数
{
int ret = 0, i;
for(i = 0; i < 9; i++) ret = ret * 10 + s[i];
return ret % maxn;
}
bool try_to_insert(int rear) //插入哈希表
{
int h = Hash(st[rear]);
for(int e = head[h]; e != -1; e = nxt[e])
{
if(memcmp(st[e], st[rear], sizeof(st[e])) == 0) return 0;
}
nxt[rear] = head[h];
head[h] = rear;
return 1;
}
int bfs() //遍历
{
int frt = 1, rear = 2, i, z;
while(frt < rear)
{
State& s = st[frt];
if(memcmp(s, goal, sizeof(s)) == 0) return frt;
for(z = 0; s[z] != 0; z++);
int x = z / 3;
int y = z % 3;
for(i = 0; i < 4; i++)
{
int newx = x + dx[i];
int newy = y + dy[i];
int newz = 3 * newx + newy;
if(newx >= 0 && newx < 3 && newy >= 0 && newy < 3)
{
State& news = st[rear];
memcpy(news, s, sizeof(s));
news[z] = s[newz];
news[newz] = 0;
if(try_to_insert(rear))
{
fa[rear] = frt;
switch(i)
{
case 0: dir[rear] = 'u'; break;
case 1: dir[rear] = 'd'; break;
case 2: dir[rear] = 'l'; break;
case 3: dir[rear] = 'r'; break;
default: break;
}
rear++;
}
}
}
frt++;
}
return 0;
}
void print(int i) //输出
{
if(fa[i] == -1) return;
print(fa[i]);
cout<<dir[i];
}
int main()
{
char c[10];
int i, ret;
while(cin>>c[0]>>c[1]>>c[2]>>c[3]>>c[4]>>c[5]>>c[6]>>c[7]>>c[8])
{
for(i = 0; i < 9; i++) st[1][i] = c[i] == 'x' ? 0 : (int)(c[i]-'0');
memset(head, -1, sizeof(head));
fa[1] = -1;
ret = bfs();
if(ret)
{
print(ret);
}
else cout<<"unsolvable";
cout<<endl;
}
return 0;
}
相关文章推荐
- POJ 1077 Eight(BFS Hash)
- POJ 1077 Eight(据说此题不做人生不完整~~~)
- POJ 1077 Eight, 八数码问题
- poj 1077 Eight(BFS + 康托判重)
- poj 1077-Eight;hdu 1043-Eight
- hdu 1034 & poj 1077 Eight 传说中的八数码问题。真是一道神题,A*算法+康托展开
- HDU 1043 Eight(经典八数码问题)对比POJ 1077
- POJ 1077 Eight(单向搜索)
- POJ 1077 Eight(BFS:输出路径)
- hdu 1043 eight(poj 1077) (bfs)
- poj 1077 Eight (bfs A* IDA*)
- POJ_1077_Eight(八数码)
- poj 1077-Eight(八数码+逆向bfs打表)
- POJ 1077 Eight 八数码问题[康托展开 + BFS]
- POJ 1077 Eight & HDU 1043 Eight(康托展开+BFS)
- POJ 1077 Eight
- POJ 1077 Eight 八数码 DBFS
- poj 1077 Eight
- poj 1077 Eight(经典八数码问题:bfs/Dbfs)
- POJ 1077 Eight