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 < ...
随机推荐
- cf487C Prefix Product Sequence
Consider a sequence [a1, a2, ... , an]. Define its prefix product sequence . Now given n, find a per ...
- 生日聚会 BZOJ 1037
生日聚会 [问题描述] 今天是hidadz小朋友的生日,她邀请了许多朋友来参加她的生日party. hidadz带着朋友们来到花园中,打算坐成一排玩游戏.为了游戏不至于无聊,就座的方案应满足如下条件: ...
- 标准C程序设计七---07
Linux应用 编程深入 语言编程 标准C程序设计七---经典C11程序设计 以下内容为阅读: <标准C程序设计>(第7版) 作者 ...
- mysql续
接上篇博客,写完以后看了看,还是觉的写的太简单,就算是自己复习都不够,所以再补充一些 1.创建多表关联 需求:图书管理系统,创建几张表,包含书籍,出版社,作者,作者详细信息等内容 分析: (1)图书只 ...
- golang导出Excel表格
设置样式: package main import ( "github.com/tealeg/xlsx" "fmt" ) func main() { var f ...
- Jenkins持续部署-Windows环境持续部署探究1
目录 Jenkins持续部署-Windows环境持续部署探究1 目录 前言 目的 方案流程 技术实现 PowerShell FTP上传插件 环境变量插件 脚本执行 远程调用 升级服务 启动服务 总结 ...
- pyserial安装
参考网址:pyserial.sourceforge.net/pyserial.html#installation Download the archive from http://pypi.pytho ...
- LeetCode第一题以及时间复杂度的计算
问题描述:给定一组指定整数数组,找出数组中加和等于特定数的两个数. 函数(方法)twoSum返回这两个数的索引,index1必须小于index2. 另外:你可以假设一个数组只有一组解. 一个栗子: I ...
- Java的不定参数(eg:Object...)(转)
第一个例子: public class VariArgs { public static void main(String[] args) { test(); test("aaa" ...
- 【java】java 中 byte[]、File、InputStream 互相转换
========================================================================= 使用过程中,一定要注意close()掉各个读写流!! ...