主页面: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的更多相关文章

  1. 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开

    [kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...

  2. HDU 1043 Eight(反向BFS+打表+康托展开)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目大意:传统八数码问题 解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各 ...

  3. UVa 1599 理想路径(反向BFS 求最短路径 )

    题意: 给定一个有重边有自环的无向图,n个点(2 <= n <= 100000), m条边(1 <= m <= 200000), 每条边有一个权值, 求从第一个点到n的最少步数 ...

  4. 【HDU - 1043】Eight(反向bfs+康托展开)

    Eight Descriptions: 简单介绍一下八数码问题:在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图: 1 2 3 4 5 6 7 8   在上图中,由于右下角位置是空的 ...

  5. 康托展开+反向bfs

    康托展开+反向bfs hdu 1043 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1043 #include <iostream> # ...

  6. POJ3967Ideal Path[反向bfs 层次图]

    Ideal Path Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 1754   Accepted: 240 Descri ...

  7. poj1077(康托展开+bfs+记忆路径)

    题意:就是说,给出一个三行三列的数组,其中元素为1--8和x,例如: 1 2 3 现在,需要你把它变成:1 2 3 要的最少步数的移动方案.可以右移r,左移l,上移u,下移dx 4 6 4 5 67 ...

  8. 聂老师的考验(反向bfs)

    题目链接:http://113.240.233.2:8081/JudgeOnline/problem.php?id=1121 这个题看起来要多次使用bfs,其实只要换个思维就会发现这就是一个简单的bf ...

  9. POJ1077 八数码 BFS

    BFS 几天的超时... A*算法不会,哪天再看去了. /* 倒搜超时, 改成顺序搜超时 然后把记录路径改成只记录当前点的操作,把上次的位置记录下AC..不完整的人生啊 */ #include < ...

随机推荐

  1. Maven常用参数及其说明【转:http://blog.csdn.net/wangjunjun2008/article/details/18982089】

    Maven常用参数及其说明 -h,--help                              Display help information-am,--also-make         ...

  2. android源码mk文件里的TARGET_OUT指向哪里?

    android源码核心变量大都在build/core/envsetup.mk中建立 在该文件中,可以找到 TARGET_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ ...

  3. 实战分析Tomcat的类加载器结构(使用Eclipse MAT验证)

    一.前言 在各种Tomcat相关书籍,书上都提到了其类加载器结构: 在Tomcat 7或者8中,共享类和Catalina类加载器在catalina.properties中都是没配置的,请看: 所以,c ...

  4. angular中ng-class的一些用法

    在前面Angularjs开发一些经验总结中我们说到在angular开发中angular controller never 包含DOM元素(html/css),在controller需要一个简单的POJ ...

  5. nosql整理

    Nosql: Redis,Memcache,MongoDB,Hbase,Couchbase  LevelDB https://www.cnblogs.com/lina520/p/7919551.htm ...

  6. lnux 下 core文件

    1. core文件的简单介绍在一个程序崩溃时,它一般会在指定目录下生成一个core文件.core文件仅仅是一个内存映象(同时加上调试信息),主要是用来调试的. 2. 开启或关闭core文件的生成用以下 ...

  7. POJ 3694 (tarjan缩点+LCA+并查集)

    好久没写过这么长的代码了,题解东哥讲了那么多,并查集优化还是很厉害的,赶快做做前几天碰到的相似的题. #include <iostream> #include <algorithm& ...

  8. ZOJ - 4020 Traffic Light (BFS)

    [传送门]http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4020 [题目大意]从起点(sx, sy)出发,要到达(ex , ...

  9. Linux C多线程编程-线程互斥

    Linux下的多线程编程需要注意的是程序需要包含头文件pthread.h,在生成可执行文件的时候需要链接库libpthread.a或者libpthread.so. 线程创建函数: pthread_cr ...

  10. SystemTap使用技巧 1 - 4 非常重要

    http://blog.csdn.net/wangzuxi/article/details/42849053