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

  1. POJ1915Knight Moves(单向BFS + 双向BFS)

    题目链接 单向bfs就是水题 #include <iostream> #include <cstring> #include <cstdio> #include & ...

  2. HDU 3085 Nightmare II 双向bfs 难度:2

    http://acm.hdu.edu.cn/showproblem.php?pid=3085 出的很好的双向bfs,卡时间,普通的bfs会超时 题意方面: 1. 可停留 2. ghost无视墙壁 3. ...

  3. POJ 3170 Knights of Ni (暴力,双向BFS)

    题意:一个人要从2先走到4再走到3,计算最少路径. 析:其实这个题很水的,就是要注意,在没有到4之前是不能经过3的,一点要注意.其他的就比较简单了,就是一个双向BFS,先从2搜到4,再从3到搜到4, ...

  4. [转] 搜索之双向BFS

    转自:http://www.cppblog.com/Yuan/archive/2011/02/23/140553.aspx 如果目标也已知的话,用双向BFS能很大程度上提高速度. 单向时,是 b^le ...

  5. 双向BFS

    转自“Yuan” 如果目标也已知的话,用双向BFS能很大提高速度 单向时,是 b^len的扩展. 双向的话,2*b^(len/2)  快了很多,特别是分支因子b较大时 至于实现上,网上有些做法是用两个 ...

  6. HDU 3085 Nightmare Ⅱ (双向BFS)

    Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  7. HDU 3085 Nightmare Ⅱ 双向BFS

    题意:很好理解,然后注意几点,男的可以一秒走三步,也就是三步以内的都可以,鬼可以穿墙,但是人不可以,鬼是一次走两步 分析:我刚开始男女,鬼BFS三遍,然后最后处理答案,严重超时,然后上网看题解,发现是 ...

  8. POJ 3126 Prime Path 解题报告(BFS & 双向BFS)

    题目大意:给定一个4位素数,一个目标4位素数.每次变换一位,保证变换后依然是素数,求变换到目标素数的最小步数. 解题报告:直接用最短路. 枚举1000-10000所有素数,如果素数A交换一位可以得到素 ...

  9. Hdu1401-Solitaire(双向bfs)

    Solitaire is a game played on a chessboard 8x8. The rows and columns of the chessboard are numbered ...

随机推荐

  1. msp430入门学习43

    msp430的其他十一 msp430入门学习

  2. StringBuffer笔记

    简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 Strin ...

  3. Java生成读取条形码和二维码图片

    原文:http://www.open-open.com/code/view/1453520722495 package zxing; import com.google.zxing.BarcodeFo ...

  4. mysqldump 把数据库备份到异地的服务器

    原文:http://www.open-open.com/code/view/1420121471484 这个方法可以把通过mysqldump 把本地数据库备份到远端主机, 中间数据的传输通过 ssh ...

  5. 聊聊WiFi Hacks:为何你的Karma攻击不好使了

    0.前言 三年前我发表了一篇文章<黑客有办法让你自动连上陌生WiFi>,介绍Karma攻击可以让你的无线设备自动连上黑客的WiFi.当时引起了还算比较热烈的讨论,关于WiFi安全,关于Ka ...

  6. Node.js机制及原理理解初步

    http://blog.csdn.net/leftfist/article/details/41891407 一.node.js优缺点 node.js是单线程. 好处就是 1)简单 2)高性能,避免了 ...

  7. winform中使用ReportViewer的时候,找不到报表数据面板.

    最近在做winform的报表项目,看人家教程里都有报表数据面板,可我的怎么都找不到,我的是VS2012,最后终于找到,首先必须在报表设计TAB上(选中它),然后选择视图->报表数据

  8. 【转载】轻松搞懂WebService工作原理

    用更简单的方式给大家谈谈WebService,让你更快更容易理解,希望对初学者有所帮助. WebService是基于网络的.分布式的模块化组件. 我们直接来看WebService的一个简易工作流程: ...

  9. [游戏]L4D求生之路官方比赛地图修补完好说明

    游戏模式:L4D求生之路4356(1.0.2.1)药抗比赛模式 更新日期:2015.06.04 -----毫不留情01----- 1.开局补给手枪 -----毫不留情02----- 1.开局补给手枪 ...

  10. 标准C头文件

    ISO C标准定义的头文件: POSIX标准定义的必须的头文件: POSIX标准定义的XSI可选头文件: POSIX标准定义的可选头文件: