POJ1077 Eight —— 双向BFS
主页面:http://www.cnblogs.com/DOLFAMINGO/p/7538588.html
(代码一直在精简完善……)
代码一:两个BFS, 两段代码; 用step控制“你一步, 我一步”。
#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 step; //双向bfs需要记录第几步,才能做到“你一步,我一步”
}; int fac[] = { , , , , , , , , };
int dir1[][] = { -,, ,, ,-, , }; //正方向
char op1[] = {'u', 'd', 'l', 'r' };
int dir2[][] = {,, ,-, ,, -,}; //反方向
char op2[] = {'l', 'r', 'u', 'd' }; char path1[MAXN], path2[MAXN]; //1为正方向,2为反方向,以下皆如此
int pre1[MAXN], pre2[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>q1, q2;
int vis1[MAXN], vis2[MAXN];
int bfs(node now)
{
ms(vis1,);
ms(vis2,);
while(!q1.empty()) q1.pop();
while(!q2.empty()) q2.pop(); now.status = cantor(now.s);
now.step = ;
pre1[now.status] = -;
vis1[now.status] = ;
q1.push(now); for(int i = ; i<; i++)
now.s[i] = i+;
now.loc = ;
now.status = cantor(now.s);
now.step = ;
pre2[now.status] = -;
vis2[now.status] = ;
q2.push(now); int time = ; //计时器
while(!q1.empty() || !q2.empty())
{
time++;
while(!q1.empty())
{
if(q1.front().step==time) //时间到了,就让给对方
break; now = q1.front();
q1.pop(); if(vis2[now.status]) //此状态已被对方访问过,则说明两者“接上了”
return now.status; int x = now.loc/;
int y = now.loc%;
for(int i = ; i<; i++)
{
int xx = x + dir1[i][];
int yy = y + dir1[i][];
if(xx>= && xx<= && yy>= && yy<=)
{
node tmp = now;
tmp.s[x*+y] = tmp.s[xx*+yy];
tmp.s[xx*+yy] = ;
tmp.status = cantor(tmp.s);
if(!vis1[tmp.status])
{
vis1[tmp.status] = ;
tmp.loc = xx*+yy;
tmp.step++;
path1[tmp.status] = op1[i];
pre1[tmp.status] = now.status;
q1.push(tmp);
}
}
}
} while(!q2.empty())
{
if(q2.front().step==time) //时间到了,就让给对方
break; now = q2.front();
q2.pop(); if(vis1[now.status]) //此状态已被对方访问过,则说明两者“接上了”
return now.status; int x = now.loc/;
int y = now.loc%;
for(int i = ; i<; i++)
{
int xx = x + dir2[i][];
int yy = y + dir2[i][];
if(xx>= && xx<= && yy>= && yy<=)
{
node tmp = now;
tmp.s[x*+y] = tmp.s[xx*+yy];
tmp.s[xx*+yy] = ;
tmp.status = cantor(tmp.s);
if(!vis2[tmp.status])
{
vis2[tmp.status] = ;
tmp.loc = xx*+yy;
tmp.step++;
path2[tmp.status] = op2[i];
pre2[tmp.status] = now.status;
q2.push(tmp);
}
}
}
}
}
return -;
} void Print1(int status) //输出正方向的路径
{
if(pre1[status]==-) return;
Print1(pre1[status]);
putchar(path1[status]);
} void Print2(int status) //输出反方向的路径
{
if(pre2[status]==-) return;
putchar(path2[status]);
Print2(pre2[status]);
} 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 status = bfs(beg);
if(status==-)
puts("unsolvable");
else
{
Print1(status); Print2(status); //输出路径
putchar('\n');
}
}
}
代码二:两个BFS, 两段代码; 用队列的大小控制“你一步, 我一步”。
#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 fac[] = { , , , , , , , , };
int dir1[][] = { -,, ,, ,-, , }; //正方向
char op1[] = {'u', 'd', 'l', 'r' };
int dir2[][] = {,, ,-, ,, -,}; //反方向
char op2[] = {'l', 'r', 'u', 'd' }; char path1[MAXN], path2[MAXN]; //1为正方向,2为反方向,以下皆如此
int pre1[MAXN], pre2[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>q1, q2;
int vis1[MAXN], vis2[MAXN];
int bfs(node now)
{
ms(vis1,);
ms(vis2,);
while(!q1.empty()) q1.pop();
while(!q2.empty()) q2.pop(); now.status = cantor(now.s);
pre1[now.status] = -;
vis1[now.status] = ;
q1.push(now); for(int i = ; i<; i++)
now.s[i] = i+;
now.loc = ;
now.status = cantor(now.s);
pre2[now.status] = -;
vis2[now.status] = ;
q2.push(now); while(!q1.empty() || !q2.empty())
{
int s1 = q1.size(); //当前队列中的结点步数是一样的,处理完这些结点,得到步数+1的结点
while(s1--)
{
now = q1.front();
q1.pop(); if(vis2[now.status]) //此状态已被对方访问过,则说明两者“接上了”
return now.status; int x = now.loc/;
int y = now.loc%;
for(int i = ; i<; i++)
{
int xx = x + dir1[i][];
int yy = y + dir1[i][];
if(xx>= && xx<= && yy>= && yy<=)
{
node tmp = now;
tmp.s[x*+y] = tmp.s[xx*+yy];
tmp.s[xx*+yy] = ;
tmp.status = cantor(tmp.s);
if(!vis1[tmp.status])
{
vis1[tmp.status] = ;
tmp.loc = xx*+yy;
path1[tmp.status] = op1[i];
pre1[tmp.status] = now.status;
q1.push(tmp);
}
}
}
} int s2 = q2.size();
while(s2--)
{
now = q2.front();
q2.pop(); if(vis1[now.status]) //此状态已被对方访问过,则说明两者“接上了”
return now.status; int x = now.loc/;
int y = now.loc%;
for(int i = ; i<; i++)
{
int xx = x + dir2[i][];
int yy = y + dir2[i][];
if(xx>= && xx<= && yy>= && yy<=)
{
node tmp = now;
tmp.s[x*+y] = tmp.s[xx*+yy];
tmp.s[xx*+yy] = ;
tmp.status = cantor(tmp.s);
if(!vis2[tmp.status])
{
vis2[tmp.status] = ;
tmp.loc = xx*+yy;
path2[tmp.status] = op2[i];
pre2[tmp.status] = now.status;
q2.push(tmp);
}
}
}
}
}
return -;
} void Print1(int status) //输出正方向的路径
{
if(pre1[status]==-) return;
Print1(pre1[status]);
putchar(path1[status]);
} void Print2(int status) //输出反方向的路径
{
if(pre2[status]==-) return;
putchar(path2[status]);
Print2(pre2[status]);
} 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 status = bfs(beg);
if(status==-)
puts("unsolvable");
else
{
Print1(status); Print2(status); //输出路径
putchar('\n');
}
}
}
代码三:两个队列,调用一段BFS(),用队列的大小控制“你一步, 我一步”。
#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 fac[] = { , , , , , , , , };
int dir[][][] = { -,, ,, ,-, ,, ,, ,-, ,, -,}; //正方向
char op[][] = {'u', 'd', 'l', 'r' , '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>q[];
int vis[][MAXN];
int bfs(int id)
{
int Size = q[id].size();
while(Size--)
{
node now = q[id].front();
q[id].pop(); if(vis[!id][now.status])
return now.status; int x = now.loc/;
int y = now.loc%;
for(int i = ; i<; i++)
{
int xx = x + dir[id][i][];
int yy = y + dir[id][i][];
if(xx>= && xx<= && yy>= && yy<=)
{
node tmp = now;
tmp.s[x*+y] = tmp.s[xx*+yy];
tmp.s[xx*+yy] = ;
tmp.status = cantor(tmp.s);
if(!vis[id][tmp.status])
{
vis[id][tmp.status] = ;
tmp.loc = xx*+yy;
path[id][tmp.status] = op[id][i];
pre[id][tmp.status] = now.status;
q[id].push(tmp);
}
}
}
}
return -;
} int solve(node now) //把两个bfs缩在一起写, 精简代码
{
ms(vis,);
while(!q[].empty()) q[].pop();
while(!q[].empty()) q[].pop(); now.status = cantor(now.s);
pre[][now.status] = -;
vis[][now.status] = ;
q[].push(now); for(int i = ; i<; i++)
now.s[i] = i+;
now.loc = ;
now.status = cantor(now.s);
pre[][now.status] = -;
vis[][now.status] = ;
q[].push(now); int time = , ret;
while(!q[].empty() ||!q[].empty())
{
ret = bfs();
if(ret!=-) return ret;
ret = bfs();
if(ret!=-) return ret;
time++;
}
return -;
} void Print1(int status) //输出正方向的路径
{
if(pre[][status]==-) return;
Print1(pre[][status]);
putchar(path[][status]);
} void Print2(int status) //输出反方向的路径
{
if(pre[][status]==-) return;
putchar(path[][status]);
Print2(pre[][status]);
} 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 status = solve(beg);
if(status==-)
puts("unsolvable");
else
{
Print1(status); Print2(status); //输出路径
putchar('\n');
}
}
}
代码四:一个队列(将正反两方向的结点都丢进同一个队列, 保证了“你一步我一步”), 一段BFS。
#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 id; //id标记正反方向
}; int fac[] = { , , , , , , , , };
int dir[][][] = { -,, ,, ,-, ,, ,, ,-, ,, -,}; //正方向
char op[][] = {'u', 'd', 'l', 'r' , '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;
int vis[][MAXN];
int bfs(node now) //把两个bfs缩在一起写, 精简代码
{
ms(vis,);
while(!que.empty()) que.pop(); now.status = cantor(now.s);
now.id = ;
pre[][now.status] = -;
vis[][now.status] = ;
que.push(now); for(int i = ; i<; i++)
now.s[i] = i+;
now.loc = ;
now.status = cantor(now.s);
now.id = ;
pre[][now.status] = -;
vis[][now.status] = ;
que.push(now); while(!que.empty())
{
node now = que.front();
que.pop(); if(vis[!now.id][now.status])
return now.status; int x = now.loc/;
int y = now.loc%;
for(int i = ; i<; i++)
{
int xx = x + dir[now.id][i][];
int yy = y + dir[now.id][i][];
if(xx>= && xx<= && yy>= && yy<=)
{
node tmp = now;
tmp.s[x*+y] = tmp.s[xx*+yy];
tmp.s[xx*+yy] = ;
tmp.status = cantor(tmp.s);
if(!vis[now.id][tmp.status])
{
vis[now.id][tmp.status] = ;
tmp.loc = xx*+yy;
path[now.id][tmp.status] = op[now.id][i];
pre[now.id][tmp.status] = now.status;
que.push(tmp);
}
}
}
}
} void Print1(int status) //输出正方向的路径
{
if(pre[][status]==-) return;
Print1(pre[][status]);
putchar(path[][status]);
} void Print2(int status) //输出反方向的路径
{
if(pre[][status]==-) return;
putchar(path[][status]);
Print2(pre[][status]);
} 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 status = bfs(beg);
if(status==-)
puts("unsolvable");
else
{
Print1(status); Print2(status); //输出路径
putchar('\n');
}
}
}
POJ1077 Eight —— 双向BFS的更多相关文章
- POJ1915Knight Moves(单向BFS + 双向BFS)
题目链接 单向bfs就是水题 #include <iostream> #include <cstring> #include <cstdio> #include & ...
- HDU 3085 Nightmare II 双向bfs 难度:2
http://acm.hdu.edu.cn/showproblem.php?pid=3085 出的很好的双向bfs,卡时间,普通的bfs会超时 题意方面: 1. 可停留 2. ghost无视墙壁 3. ...
- POJ 3170 Knights of Ni (暴力,双向BFS)
题意:一个人要从2先走到4再走到3,计算最少路径. 析:其实这个题很水的,就是要注意,在没有到4之前是不能经过3的,一点要注意.其他的就比较简单了,就是一个双向BFS,先从2搜到4,再从3到搜到4, ...
- [转] 搜索之双向BFS
转自:http://www.cppblog.com/Yuan/archive/2011/02/23/140553.aspx 如果目标也已知的话,用双向BFS能很大程度上提高速度. 单向时,是 b^le ...
- 双向BFS
转自“Yuan” 如果目标也已知的话,用双向BFS能很大提高速度 单向时,是 b^len的扩展. 双向的话,2*b^(len/2) 快了很多,特别是分支因子b较大时 至于实现上,网上有些做法是用两个 ...
- HDU 3085 Nightmare Ⅱ (双向BFS)
Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 3085 Nightmare Ⅱ 双向BFS
题意:很好理解,然后注意几点,男的可以一秒走三步,也就是三步以内的都可以,鬼可以穿墙,但是人不可以,鬼是一次走两步 分析:我刚开始男女,鬼BFS三遍,然后最后处理答案,严重超时,然后上网看题解,发现是 ...
- POJ 3126 Prime Path 解题报告(BFS & 双向BFS)
题目大意:给定一个4位素数,一个目标4位素数.每次变换一位,保证变换后依然是素数,求变换到目标素数的最小步数. 解题报告:直接用最短路. 枚举1000-10000所有素数,如果素数A交换一位可以得到素 ...
- Hdu1401-Solitaire(双向bfs)
Solitaire is a game played on a chessboard 8x8. The rows and columns of the chessboard are numbered ...
随机推荐
- msp430入门学习43
msp430的其他十一 msp430入门学习
- StringBuffer笔记
简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 Strin ...
- Java生成读取条形码和二维码图片
原文:http://www.open-open.com/code/view/1453520722495 package zxing; import com.google.zxing.BarcodeFo ...
- mysqldump 把数据库备份到异地的服务器
原文:http://www.open-open.com/code/view/1420121471484 这个方法可以把通过mysqldump 把本地数据库备份到远端主机, 中间数据的传输通过 ssh ...
- 聊聊WiFi Hacks:为何你的Karma攻击不好使了
0.前言 三年前我发表了一篇文章<黑客有办法让你自动连上陌生WiFi>,介绍Karma攻击可以让你的无线设备自动连上黑客的WiFi.当时引起了还算比较热烈的讨论,关于WiFi安全,关于Ka ...
- Node.js机制及原理理解初步
http://blog.csdn.net/leftfist/article/details/41891407 一.node.js优缺点 node.js是单线程. 好处就是 1)简单 2)高性能,避免了 ...
- winform中使用ReportViewer的时候,找不到报表数据面板.
最近在做winform的报表项目,看人家教程里都有报表数据面板,可我的怎么都找不到,我的是VS2012,最后终于找到,首先必须在报表设计TAB上(选中它),然后选择视图->报表数据
- 【转载】轻松搞懂WebService工作原理
用更简单的方式给大家谈谈WebService,让你更快更容易理解,希望对初学者有所帮助. WebService是基于网络的.分布式的模块化组件. 我们直接来看WebService的一个简易工作流程: ...
- [游戏]L4D求生之路官方比赛地图修补完好说明
游戏模式:L4D求生之路4356(1.0.2.1)药抗比赛模式 更新日期:2015.06.04 -----毫不留情01----- 1.开局补给手枪 -----毫不留情02----- 1.开局补给手枪 ...
- 标准C头文件
ISO C标准定义的头文件: POSIX标准定义的必须的头文件: POSIX标准定义的XSI可选头文件: POSIX标准定义的可选头文件: