POJ1077 Eight —— 反向BFS
主页面:http://www.cnblogs.com/DOLFAMINGO/p/7538588.html
代码一:以数组充当队列,利用结构体中的pre追溯上一个状态在数组(队列)中的下标:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 1e6+; struct node
{
int status;
int s[];
int loc;
char op;
int pre; //pre为上一个操作在队列中的下标,用于输出路径
}; int vis[MAXN], fac[] = { , , , , , , , , };
int dir[][] = { ,,,-, ,, -, };
char op[] = {'l', 'r', 'u', 'd' }; //由于反向操作,则方向应该反过来
int id[MAXN]; int cantor(int s[]) //获得哈希函数值
{
int sum = ;
for(int i = ; i<; i++)
{
int num = ;
for(int j = i+; j<; j++)
if(s[j]<s[i])
num++;
sum += num*fac[-i];
}
return sum+;
} node que[MAXN];
int front, rear;
void bfs()
{
ms(vis, );
front = rear = ; node now, tmp;
for(int i = ; i<; i++) //初始状态为123456789
now.s[i] = i+;
now.loc = ;
now.status = cantor(now.s);
vis[now.status] = ;
id[now.status] = rear; //初始状态在队列中的下标
que[rear++] = now; while(front!=rear)
{
now = que[front++];
int x = now.loc/;
int y = now.loc%;
for(int i = ; i<; i++)
{
int xx = x + dir[i][];
int yy = y + dir[i][];
if(xx>= && xx<= && yy>= && yy<=)
{
tmp = now;
tmp.s[x*+y] = tmp.s[xx*+yy];
tmp.s[xx*+yy] = ;
tmp.status = cantor(tmp.s);
if(!vis[tmp.status])
{
vis[tmp.status] = ;
tmp.loc = xx*+yy;
tmp.op = op[i];
tmp.pre = front-;
id[tmp.status] = rear;
que[rear++] = tmp;
}
}
}
}
} void Print(int i)
{
if(i==) return; //队列下标为0的时候为初始状态, 应返回
putchar(que[i].op); //输出操作
Print(que[i].pre); //访问BFS的上一步,但因为是反向BFS,所以对于答案来说是下一步,应放在putchar后面
} int main()
{
bfs();//反向bfs,预处理所有情况。然后在访问的时候直接输出路径
char str[];
while(gets(str))
{
node aim;
int cnt = ;
for(int i = ; str[i]; i++)
{
if(str[i]==' ') continue;
if(str[i]=='x') aim.s[cnt] = , aim.loc = cnt++;
else aim.s[cnt++] = str[i]-'';
}
aim.status = cantor(aim.s);
if(!vis[aim.status])
puts("unsolvable");
else
Print(id[aim.status]), putchar('\n');
}
}
代码二(推荐):把pre和path放在结构体外,利用当前状态status追溯上一个状态status:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 1e6+; struct node
{
int status;
int s[];
int loc;
}; int vis[MAXN], fac[] = { , , , , , , , , };
int dir[][] = { ,,,-, ,, -, };
char op[] = {'l', 'r', 'u', 'd' }; //由于反向操作,则方向应该反过来
char path[MAXN];
int pre[MAXN]; int cantor(int s[]) //获得哈希函数值
{
int sum = ;
for(int i = ; i<; i++)
{
int num = ;
for(int j = i+; j<; j++)
if(s[j]<s[i])
num++;
sum += num*fac[-i];
}
return sum+;
} queue<node>que;
void bfs()
{
ms(vis, );
while(!que.empty()) que.pop(); node now, tmp;
for(int i = ; i<; i++) //初始状态为123456789
now.s[i] = i+;
now.loc = ;
now.status = cantor(now.s);
vis[now.status] = ;
pre[now.status] = -;
que.push(now); while(!que.empty())
{
now = que.front();
que.pop();
int x = now.loc/;
int y = now.loc%;
for(int i = ; i<; i++)
{
int xx = x + dir[i][];
int yy = y + dir[i][];
if(xx>= && xx<= && yy>= && yy<=)
{
tmp = now;
tmp.s[x*+y] = tmp.s[xx*+yy];
tmp.s[xx*+yy] = ;
tmp.status = cantor(tmp.s);
if(!vis[tmp.status])
{
vis[tmp.status] = ;
tmp.loc = xx*+yy;
path[tmp.status] = op[i];
pre[tmp.status] = now.status;
que.push(tmp);
}
}
}
}
} void Print(int status)
{
if(pre[status]==-) return;
putchar(path[status]);
Print(pre[status]);
} int main()
{
bfs();//反向bfs,预处理所有情况。然后在访问的时候直接输出路径
char str[];
while(gets(str))
{
node aim;
int cnt = ;
for(int i = ; str[i]; i++)
{
if(str[i]==' ') continue;
if(str[i]=='x') aim.s[cnt] = , aim.loc = cnt++;
else aim.s[cnt++] = str[i]-'';
}
aim.status = cantor(aim.s);
if(!vis[aim.status])
puts("unsolvable");
else
Print(aim.status), putchar('\n');
}
}
POJ1077 Eight —— 反向BFS的更多相关文章
- 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开
[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...
- HDU 1043 Eight(反向BFS+打表+康托展开)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目大意:传统八数码问题 解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各 ...
- UVa 1599 理想路径(反向BFS 求最短路径 )
题意: 给定一个有重边有自环的无向图,n个点(2 <= n <= 100000), m条边(1 <= m <= 200000), 每条边有一个权值, 求从第一个点到n的最少步数 ...
- 【HDU - 1043】Eight(反向bfs+康托展开)
Eight Descriptions: 简单介绍一下八数码问题:在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图: 1 2 3 4 5 6 7 8 在上图中,由于右下角位置是空的 ...
- 康托展开+反向bfs
康托展开+反向bfs hdu 1043 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1043 #include <iostream> # ...
- POJ3967Ideal Path[反向bfs 层次图]
Ideal Path Time Limit: 10000MS Memory Limit: 65536K Total Submissions: 1754 Accepted: 240 Descri ...
- poj1077(康托展开+bfs+记忆路径)
题意:就是说,给出一个三行三列的数组,其中元素为1--8和x,例如: 1 2 3 现在,需要你把它变成:1 2 3 要的最少步数的移动方案.可以右移r,左移l,上移u,下移dx 4 6 4 5 67 ...
- 聂老师的考验(反向bfs)
题目链接:http://113.240.233.2:8081/JudgeOnline/problem.php?id=1121 这个题看起来要多次使用bfs,其实只要换个思维就会发现这就是一个简单的bf ...
- POJ1077 八数码 BFS
BFS 几天的超时... A*算法不会,哪天再看去了. /* 倒搜超时, 改成顺序搜超时 然后把记录路径改成只记录当前点的操作,把上次的位置记录下AC..不完整的人生啊 */ #include < ...
随机推荐
- Aspose.Words使用代码插入表格
Aspose.Words是一款功能强大的word文档处理控件,在不需要安装word的条件下,可进行word的创建,修改,转换等操作. Aspose.Words可以简单使用该产品提供的DocumentB ...
- poj 3461 Oulipo,裸kmp
传送门 Oulipo Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 32373 Accepted: 13093 Desc ...
- PhpStorm8 注册码
User Name : EMBRACE License Key : ===== LICENSE BEGIN =====43136-1204201000002UsvSON704l"dILe ...
- CKeditor如何实现图片上传功能
http://makaiyuan.blog.51cto.com/5819595/1049521 如何在数据库中导入excel文件内的数据:http://jingyan.baidu.com/album/ ...
- CODEVS 1245 最小的N个和 堆+排序
原题链接 http://codevs.cn/problem/1245/ 题目描述 Description 有两个长度为 N 的序列 A 和 B,在 A 和 B 中各任取一个数可以得到 N^2 个和,求 ...
- android DatePicker使用
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=&q ...
- 【spring boot jpa】hql语句报错 :antlr.NoViableAltException: unexpected token: roleName
使用场景:在spring data jpa下使用@Query("hql语句") 然后在项目启动的时候报错 hql语句报错:antlr.NoViableAltException: u ...
- iOS WKWebView添加网页加载进度条(转)
一.效果展示 WKWebProgressViewDemo.gif 二.主要步骤 1.添加UIProgressView属性 @property (nonatomic, strong) WKWebView ...
- Linux温习(三)Linux文件和文件夹管理
关于Linux文件夹的几个常见概念 路径 对文件位置信息的描写叙述机制.是指从树型文件夹中的某个文件夹层次到其内某个文件的一条通路.分为相对路径和绝对路径: 工作文件夹 登入系统后.用户始终处于某个文 ...
- 心情日记app总结 数据存储+服务+广播+listview+布局+fragment+intent+imagebutton+tabactivity+美工
---恢复内容开始--- 结果截图如下: 第一张图是程序主界面,主要是显示记事列表的一些个事件.旁边的侧拉框是自己登陆用的.可以设置密码.可以查看反馈与关于等信息. 点击第一张图片下方的图标,会显示不 ...