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 ...
随机推荐
- Lucas 卢卡斯定理
Lucas: 卢卡斯定理说白了只有一条性质 $$ C^n_m \equiv C^{n/p}_{m/p} \times C^{n \bmod p}_{m \bmod p} \ (mod \ \ p) $ ...
- 标准C程序设计七---03
Linux应用 编程深入 语言编程 标准C程序设计七---经典C11程序设计 以下内容为阅读: <标准C程序设计>(第7版) 作者 ...
- R语言入门视频笔记--1
一.数据框简要 可输入来访问mtcars这个系统自带的数据框中的mpg列 mtcars$mpg 或者输入 mtcars[c("mpg","cyl")] 来访问两 ...
- python实现显示安装进度条
一直很好奇那种安装进度条,或者启动程序时候显示的进度条是怎么实现的,学习了python之后,sys模块中有个方法可以实现,代码如下: 1 2 3 4 5 6 import sys,time ...
- 社区发现(Community Detection)算法
作者: peghoty 出处: http://blog.csdn.net/peghoty/article/details/9286905 社区发现(Community Detection)算法用来发现 ...
- BZOJ 3675 [Apio2014]序列分割 (斜率优化DP)
题目链接 BZOJ 3675 首先最后的答案和分割的顺序是无关的, 那么就可以考虑DP了. 设$f[i][j]$为做了$i$次分割,考虑前$j$个数之后的最优答案. 那么$f[i][j] = max( ...
- 未能加载文件或程序集“System.EnterpriseServices, Version=4.0.0.0或2.0.0.0
未能加载文件或程序集“System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50 ...
- sql-trace-10046-trcsess-and-tkprof
https://oracle-base.com/articles/misc/sql-trace-10046-trcsess-and-tkprof awr/statspack,sqlprofile,sq ...
- RED HAT 7 性能监控工具
https://access.redhat.com/documentation/zh-CN/Red_Hat_Enterprise_Linux/7/html/Performance_Tuning_Gui ...
- iOS开发-用keychain替代UDID
从2013-5-1日开始苹果就禁止对UUID的应用的通过了.所以我们需要用一些办法替换,下面我就是用keychain的访问替换掉UUID的. 那么,关于Keychain的应用,Apple提供了一个叫G ...