POJ1077 八数码问题
题目:八数码
网址:http://poj.org/problem?id=1077
在一个3×3的网格中,1~8这8个数字和一个“X”恰好不重不漏地分布在这3×3的网格中。
例如:
1 2 3
X 4 6
7 5 8
在游戏过程中,可以把“X”与其上、下、左、右四个方向之一的数字交换(如果存在)。
我们的目的是通过交换,使得网格变为如下排列(称为正确排列):
1 2 3
4 5 6
7 8 X
例如,示例中图形就可以通过让“X”先后与右、下、右三个方向的数字交换成功得到正确排列。
交换过程如下:
1 2 3 1 2 3 1 2 3 1 2 3
X 4 6 4 X 6 4 5 6 4 5 6
7 5 8 7 5 8 7 X 8 7 8 X
把“X”与上下左右方向数字交换的行动记录为“u”、“d”、“l”、“r”。
现在,给你一个初始网格,请你通过最少的移动次数,得到正确排列。
输入格式
输入占一行,将3×3的初始网格描绘出来。
例如,如果初始网格如下所示:
1 2 3
x 4 6
7 5 8
则输入为:1 2 3 x 4 6 7 5 8
输出格式
输出占一行,包含一个字符串,表示得到正确排列的完整行动记录。如果答案不唯一,输出任意一种合法方案即可。
如果不存在解决方案,则输出”unsolvable”。
输入样例:
2 3 4 1 5 x 7 6 8
输出样例:
ullddrurdllurdruldr
很经典的一道广搜题目(A*)。核心就是如何保存状态。
- 方法一:使用map来记录操作以及set判重。
- 方法二:康托展开(早晚更新的)。
- 方法三:hash表判重,码量较大。
STL代码如下:
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define pii pair <int, int>
using namespace std;
const int dx[4] = {-1, 1, 0, 0};
const int dy[4] = {0, 0, -1, 1};
int st, ed = 123456780;
set <int> vis;
map <int, int> d, f;
void decode(int state, int *p)
{
for(int i = 0; i < 9; ++ i)
{
p[8 - i] = state % 10;
state /= 10;
}
return;
}
int encode(int *p)
{
int t = 0;
for(int i = 0; i < 9; ++ i)
{
t = (t << 3) + (t << 1);
t += p[i];
}
return t;
}
int gh(int *p)
{
int cost = 0;
for(int i = 0; i < 9; ++ i)
cost += abs(i / 3 - (p[i] - 1) / 3) + abs(i % 3 - (p[i] - 1) % 3);
return cost;
}
void print(int state)
{
if(state == st) return;
int pre_state = f[state];
print(pre_state);
int i, p1[9] = {}, p2[9] = {}, t1 = -1, t2 = -1;
decode(state, p1), decode(pre_state, p2);
for(i = 0; i < 9; ++ i)
{
if(p1[i] == 0)
{
t1 = i;
break;
}
}
for(i = 0; i < 9; ++ i)
{
if(p2[i] == 0)
{
t2 = i;
break;
}
}
if(t1 < t2)
{
if(t1 - t2 == -1) putchar('l');
else putchar('u');
}
else
{
if(t2 - t1 == -1) putchar('r');
else putchar('d');
}
return;
}
bool valid(int x, int y)
{
if(x < 0 || x > 2 || y < 0 || y > 2) return false;
return true;
}
bool hash_table_judge(int state)
{
if(vis.count(state)) return false;
return true;
}
void hash_table_insert(int next_state, int state)
{
d[next_state] = d[state] + 1;
vis.insert(next_state);
f[next_state] = state;
return;
}
int bfs()
{
if(st == ed) return 0;
d.clear(), vis.clear(), f.clear();
queue <int> Q;
while(!Q.empty()) Q.pop();
int state, next_state, now, next, p[9], x, y;
memset(p, -1, sizeof(p));
hash_table_insert(st, 0);
d[st] = 0;
Q.push(st);
while(!Q.empty())
{
state = Q.front();
Q.pop();
decode(state, p);
for(int i = 0; i < 9; ++ i)
{
if(p[i] == 0)
{
now = i;
x = i / 3, y = i % 3;
break;
}
}
for(int i = 0; i < 4; ++ i)
{
if(!valid(x + dx[i], y + dy[i])) continue;
next = (x + dx[i]) * 3 + (y + dy[i]);
swap(p[now], p[next]);
next_state = encode(p);
swap(p[now], p[next]);
if(!hash_table_judge(next_state)) continue;
hash_table_insert(next_state, state);
if(next_state == ed)
{
printf("%d\n", d[state]);
print(state);
return 1;
}
Q.push(next_state);
}
}
return -1;
}
int main()
{
string line;
getline(cin, line);
for(int i = 0; i < line.size(); ++ i)
{
if(line[i] == 'x')
{
line[i] = '0';
break;
}
}
stringstream ss(line);
int tmp;
st = 0;
for(int i = 0; i < 9; ++ i)
{
ss >> tmp;
st = (st << 3) + (st << 1);
st += tmp;
}
if(bfs() == -1) puts("unsolvable");
return 0;
}
hash表代码如下:
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#define pii pair <int, int>
using namespace std;
const int maxn = 377777 + 5, mod = 377777;
const int dx[4] = {-1, 1, 0, 0};
const int dy[4] = {0, 0, -1, 1};
int st, ed = 123456780, head[maxn] = {}, next[maxn] = {}, table[maxn] = {}, tot = 0;
map <int, int> d, f;
void decode(int state, int *p)
{
for(int i = 0; i < 9; ++ i)
{
p[8 - i] = state % 10;
state /= 10;
}
return;
}
int encode(int *p)
{
int t = 0;
for(int i = 0; i < 9; ++ i)
{
t = (t << 3) + (t << 1);
t += p[i];
}
return t;
}
int hash_table_search(int state)
{
int val = state % mod;
for(int i = head[val]; i; i = next[i])
if(table[i] == state) return i;
return -1;
}
int gh(int *p)
{
int cost = 0;
for(int i = 0; i < 9; ++ i)
cost += abs(i / 3 - (p[i] - 1) / 3) + abs(i % 3 - (p[i] - 1) % 3);
return cost;
}
void print(int state)
{
if(state == st) return;
int pre_state = f[state];
print(pre_state);
int i, p1[9] = {}, p2[9] = {}, t1 = -1, t2 = -1;
decode(state, p1), decode(pre_state, p2);
for(i = 0; i < 9; ++ i)
{
if(p1[i] == 0)
{
t1 = i;
break;
}
}
for(i = 0; i < 9; ++ i)
{
if(p2[i] == 0)
{
t2 = i;
break;
}
}
if(t1 < t2)
{
if(t1 - t2 == -1) putchar('l');
else putchar('u');
}
else
{
if(t2 - t1 == -1) putchar('r');
else putchar('d');
}
return;
}
bool valid(int x, int y)
{
if(x < 0 || x > 2 || y < 0 || y > 2) return false;
return true;
}
bool hash_table_judge(int state)
{
int val = state % mod;
for(int i = head[val]; i; i = next[i])
if(table[i] == state) return false;
return true;
}
void hash_table_insert(int next_state, int state)
{
int val = next_state % mod;
table[++ tot] = next_state;
next[tot] = head[val];
head[val] = tot;
f[next_state] = state;
d[next_state] = d[state] + 1;
return;
}
int bfs()
{
if(st == ed) return 0;
d.clear(), f.clear();
queue <int> Q;
while(!Q.empty()) Q.pop();
int state, next_state, now, next, p[9], x, y;
memset(p, -1, sizeof(p));
hash_table_insert(st, 0);
d[st] = 0;
Q.push(st);
while(!Q.empty())
{
state = Q.front();
Q.pop();
decode(state, p);
for(int i = 0; i < 9; ++ i)
{
if(p[i] == 0)
{
now = i;
x = i / 3, y = i % 3;
break;
}
}
for(int i = 0; i < 4; ++ i)
{
if(!valid(x + dx[i], y + dy[i])) continue;
next = (x + dx[i]) * 3 + (y + dy[i]);
swap(p[now], p[next]);
next_state = encode(p);
swap(p[now], p[next]);
if(!hash_table_judge(next_state)) continue;
hash_table_insert(next_state, state);
if(next_state == ed)
{
print(state);
return d[state];
}
Q.push(next_state);
}
}
return -1;
}
int main()
{
string line;
getline(cin, line);
for(int i = 0; i < line.size(); ++ i)
{
if(line[i] == 'x')
{
line[i] = '0';
break;
}
}
stringstream ss(line);
int tmp;
st = 0;
for(int i = 0; i < 9; ++ i)
{
ss >> tmp;
st = (st << 3) + (st << 1);
st += tmp;
}
if(bfs() == -1) puts("unsolvable");
return 0;
}
POJ1077 八数码问题的更多相关文章
- POJ1077 八数码 BFS
BFS 几天的超时... A*算法不会,哪天再看去了. /* 倒搜超时, 改成顺序搜超时 然后把记录路径改成只记录当前点的操作,把上次的位置记录下AC..不完整的人生啊 */ #include < ...
- ACM/ICPC 之 BFS-广搜进阶-八数码(经典)(POJ1077+HDU1043)
八数码问题也称为九宫问题.(本想查查历史,结果发现居然没有词条= =,所谓的历史也就不了了之了) 在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个 ...
- 由八数码问题引入。对BFS有更深考虑
12号到今天共研究八数码问题poj1077,首先用的是普通BFS,遇到很多问题,开始用一个二级指针作为结构成员,知道了二级指针与二维数值名的不同!http://write.blog.csdn.net/ ...
- A*算法 -- 八数码问题和传教士过河问题的代码实现
前段时间人工智能的课介绍到A*算法,于是便去了解了一下,然后试着用这个算法去解决经典的八数码问题,一开始写用了挺久时间的,后来试着把算法的框架抽离出来,编写成一个通用的算法模板,这样子如果以后需要用到 ...
- 八数码问题:C++广度搜索实现
毕竟新手上路23333,有谬误还请指正. 课程设计遇到八数码问题(这也是一坨),也查过一些资料并不喜欢用类函数写感觉这样规模小些的问题没有必要,一开始用深度搜索却发现深搜会陷入无底洞,如果设定了深度限 ...
- BFS(八数码) POJ 1077 || HDOJ 1043 Eight
题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状 ...
- 双向广搜+hash+康托展开 codevs 1225 八数码难题
codevs 1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Yours和zero在研究A*启 ...
- UVALive 6665 Dragonâs Cruller --BFS,类八数码问题
题意大概就是八数码问题,只不过把空格的移动方式改变了:空格能够向前或向后移动一格或三格(循环的). 分析:其实跟八数码问题差不多,用康托展开记录状态,bfs即可. 代码: #include <i ...
- P1379 八数码问题
aoapc上的八数码问题,在luogu上也有类似的题,p1379,经典题目,lrj给出了一个算法,同时给出了三种判重的方法.本来想用std::queue改写一下,但是出了各种问题,只好抄代码ac掉这道 ...
随机推荐
- 牛客寒假基础集训营 | Day1 J题—u's的影响力(水题)
Day1 J题-u's的影响力 有一天,kotori发现了一个和lovelive相似的游戏:bangdream.令她惊讶的是,这个游戏和lovelive居然是同一个公司出的! kotori经过一段时间 ...
- STL(六)——map、multimap
STL--map.multimap 文章目录 STL--map.multimap 关联容器与map的介绍 map与set的异同 map与multimap的异同 map类对象的构造 map添加元素 ma ...
- webpack4.x 从零开始配置vue 项目(三)
目标 babel 转换ES6 语法 postCss 增强css功能,如自动增加前缀 vue-loader 解析vue 文件 实现基本的vue项目开发环境,打包等 Babel 由于浏览器对es6语法兼容 ...
- DOM--选取文档元素
大多数的客户端JavaScript程序在运行时都是在操作一个或者多个文档元素,而为了操作文档中的元素我们就必须要通过某种途径或者方法获得或者选取这些引用文档元素的Element对象.DOM定义了许多种 ...
- 1068 Find More Coins (30分)(dp)
Eva loves to collect coins from all over the universe, including some other planets like Mars. One d ...
- Scratch 全套学习资料
链接:https://pan.baidu.com/s/1qX0T2B_zczcLaCCpiRrsnA提取码:xfp8
- 【mysql】用navicat无法连接mysql时解决方法
1.进入数据库 2.输入 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION;
- .net core 实现excel 和 word 的在线预览
最新在搞文件的在线预览,网上很多免费的方案都需要是电脑安装office的,这要就很麻烦:收费的插件又太贵了. 不过还是找到一款相对好用的免费在线预览插件. 直接在nuget上搜索ce.office.e ...
- buuctf misc wp 01
buuctf misc wp 01 1.金三胖 2.二维码 3.N种方法解决 4.大白 5.基础破解 6.你竟然赶我走 1.金三胖 root@kali:~/下载/CTF题目# unzip 77edf3 ...
- 智能指针 shared_ptr
1.不支持数组 2.c++11支持make_shared,分配一次内存,构造函数为private和proteced时不能调用. 3.new初始化分配两次内存,一.分配数据块内存,二.分配控制块内存