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+;
#define AIM 1 //123456789的哈希值为1 struct node
{
int status;
int s[];
int loc;
char path;
int pre; //pre为上一个操作在队列中的下标,用于输出路径
}; int vis[MAXN], fac[] = { , , , , , , , , };
int dir[][] = { -,, ,, ,-, , };
char op[] = {'u', 'd', 'l', 'r' }; 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;
int bfs(node now)
{
ms(vis,);
front = rear = ; now.status = cantor(now.s);
vis[now.status] = ;
que[rear++] = now; node tmp;
while(front!=rear)
{
now = que[front++];
if(now.status==AIM)
return 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.path = op[i]; //保存操作
tmp.pre = front-; //保存当前结点的状态的上一个状态所在的结点在数组(队列)的下标
que[rear++] = tmp;
}
}
}
}
return -;
} void Print(int i) //利用递归的特点(压栈),输出路径
{
if(i==) return; //到了目的状态,则退出。目的状态的结点在数组(队列)中的下标为0
Print(que[i].pre); //访问上一步
putchar(que[i].path); //输出操作
} int main()
{
char tmp[];
while(gets(tmp))
{
node beg;
int cnt = ;
for(int i = ; tmp[i]; i++)
{
if(tmp[i]==' ') continue;
if(tmp[i]=='x') beg.s[cnt] = , beg.loc = cnt++;
else beg.s[cnt++] = tmp[i]-''; }
int i = bfs(beg);
if(i==-)
puts("unsolvable");
else
Print(i), 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+;
#define AIM 1 //123456789的哈希值为1 struct node
{
int status;
int s[];
int loc;
}; int vis[MAXN], fac[] = { , , , , , , , , };
int dir[][] = { -,, ,, ,-, , };
char op[] = {'u', 'd', 'l', 'r' };
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;
bool bfs(node now)
{
ms(vis,);
while(!que.empty()) que.pop(); now.status = cantor(now.s);
pre[now.status] = -; //开始状态的上一个状态为-1,用于输出路径时“刹车”
vis[now.status] = ;
que.push(now); node tmp;
while(!que.empty())
{
now = que.front();
que.pop();
if(now.status==AIM) //找到了123456789的状态
return true; 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;
pre[tmp.status] = now.status; //tmp.status的上一个状态为now.status
path[tmp.status] = op[i]; //保存操作
que.push(tmp);
}
}
}
}
return ;
} void Print(int status)
{
if(pre[status]==-) return;
Print(pre[status]); //追溯上一个状态
putchar(path[status]);
} int main()
{
char str[];
while(gets(str))
{
node now;
int cnt = ;
for(int i = ; str[i]; i++)
{
if(str[i]==' ') continue;
if(str[i]=='x') now.s[cnt] = , now.loc = cnt++;
else now.s[cnt++] = str[i]-'';
}
if(!bfs(now))
puts("unsolvable");
else
Print(AIM), putchar('\n');
}
}
POJ1077 Eight —— 正向BFS的更多相关文章
- poj1077(康托展开+bfs+记忆路径)
题意:就是说,给出一个三行三列的数组,其中元素为1--8和x,例如: 1 2 3 现在,需要你把它变成:1 2 3 要的最少步数的移动方案.可以右移r,左移l,上移u,下移dx 4 6 4 5 67 ...
- POJ1077 八数码 BFS
BFS 几天的超时... A*算法不会,哪天再看去了. /* 倒搜超时, 改成顺序搜超时 然后把记录路径改成只记录当前点的操作,把上次的位置记录下AC..不完整的人生啊 */ #include < ...
- POJ1077 Eight —— 双向BFS
主页面:http://www.cnblogs.com/DOLFAMINGO/p/7538588.html (代码一直在精简完善……) 代码一:两个BFS, 两段代码: 用step控制“你一步, 我一步 ...
- POJ1077 Eight —— 反向BFS
主页面:http://www.cnblogs.com/DOLFAMINGO/p/7538588.html 代码一:以数组充当队列,利用结构体中的pre追溯上一个状态在数组(队列)中的下标: #incl ...
- POJ1077 Eight —— 经典的搜索问题
题目链接:http://poj.org/problem?id=1077 Eight Time Limit: 1000MS Memory Limit: 65536K Total Submission ...
- 逆向+两次bfs(UVA 1599)
为什么都说简单好想咧.坦白从宽看了人家的代码,涨了好多姿势,, http://blog.csdn.net/u013382399/article/details/38227917 被一个细节坑了.. 2 ...
- 双向BFS—>NOIP2002 字串变换
如果目标也已知的话,用双向BFS能很大提高速度 单向时,是 b^len的扩展. 双向的话,2*b^(len/2) 快了很多,特别是分支因子b较大时 至于实现上,网上有些做法是用两个队列,交替节点搜索 ...
- BFS && DFS
HDOJ 1312 Red and Black http://acm.hdu.edu.cn/showproblem.php?pid=1312 很裸的dfs,在dfs里面写上ans++,能到几个点就调了 ...
- UVa1599 Ideal Path(双向bfs+字典序+非简单图的最短路+队列判重)
题目大意: 对于一个n个房间m条路径的迷宫(Labyrinth)(2<=n<=100000, 1<=m<=200000),每条路径上都涂有颜色,颜色取值范围为1<=c&l ...
随机推荐
- 染色(bzoj 2243)
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...
- hdu 4849
简单题,公式计算+最短路.注意点:注意1 取模,2 数组开到n*n+n. #include<iostream> #include<queue> using namespace ...
- hdu4862 2014多校B题/ 费用流(最优情况下用不大于K条路径覆盖)(不同的解法)
题意: 一个数字矩阵,可以出发K次,每次可以从右边或者下面走,要求(在收益最大情况下)覆盖全图,不能则输出-1.(规则:每次跳一步的时候若格子数字相等则获得该数字的能量,每跳一步消耗距离的能量).每个 ...
- AC日记——租用游艇 洛谷 P1359
题目描述 长江游艇俱乐部在长江上设置了n 个游艇出租站1,2,…,n.游客可在这些游艇出租站租用游艇,并在下游的任何一个游艇出租站归还游艇.游艇出租站i 到游艇出租站j 之间的租金为r(i,j),1& ...
- c++ 高效并发编程
高效并发编程 并发编程的基本模型包括,通过消息机制来管理运行顺序的message passing, 通过互斥保护共享的shared memory. 线程同步的基本原则 最低限度共享变量,考虑使用imm ...
- PAT (Advanced Level) 1087. All Roads Lead to Rome (30)
暴力DFS. #include<cstdio> #include<cstring> #include<cmath> #include<vector> # ...
- Centos7配置Grafana对接OpenLDAP
在grafana的主配置文件grafana.ini中开启LDAP认证 注意:grafana有两个地方需要指定(/etc/grafana/grafana.ini和/usr/share/grafana/c ...
- 【C语言天天练(九)】动态内存分配
引言:数组的元素存储于内存中连续的位置上.当一个数组被声明时.它所须要的内存在编译时就被分配. 可是,我们能够使用动态内存分配在执行时为它分配内存. 一块内存的生命周期能够分为四个阶段:分配.初始化. ...
- 卸载 linux http
当我们想卸载httpd 的时候,使用rpm -qa httpd 的时候,我们发现有很多的依赖包.我们耐心的想一个一个的卸载的时候(使用rpm -e httpd-*),还会进入死循环.解决的办法是:使用 ...
- nc和telnet配合使用
nc -l 9932 -c 用nc监听9932端口 telnet 180.150.184.115 29933 telnet 29932 端口