主页面: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. MyBatipse插件

    MyBatipse:Eclipse 下的 Mybatis插件 MyBatipse是Eclipse的一个插件,提供了内容提示和Mybatis的配置文件验证功能: 特点 XMLEditor 的增强 代码自 ...

  2. spring 容器bean

    bean配置信息----> 读取bean的配置信息到bean的注册表中---> 根据注册表的信息实例化bean---> 将bean的实例放到spring的容器中---> 应用程 ...

  3. Codeforces Round #284 (Div. 2) D. Name That Tune [概率dp]

    D. Name That Tune time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  4. 模拟赛QAQ

    100 + 30 + 0 T1 叉叉 题目描述 现在有一个字符串,每个字母出现的次数均为偶数.接下来我们把第一次出现的字母a和第二次出现的a连一条线,第三次出现的和四次出现的字母a连一条线,第五次出现 ...

  5. usaco feb04距离咨询

    [USACO FEB04]距离咨询 成绩   开启时间 2014年09月19日 星期五 10:08 折扣 0.8 折扣时间 2014年09月26日 星期五 10:08 允许迟交 是 关闭时间 2014 ...

  6. Hibernate 与Mybatis之比较

    1. hibernate是全自动,而mybatis是半自动.hibernate完全可以通过对象关系模型实现对数据库的操作,拥有完整的JavaBean对象与数据库的映射结构来自动生成sql.而mybat ...

  7. 转: 在CentOS 6.X 上面安装 Python 2.7.X

    转:https://ruiaylin.github.io/2014/12/12/python%20update/ 评注: yum -y update //这个更新太坑了,1120更新包...想死的心都 ...

  8. PAT 1003 Sharing (25)

    题目描写叙述 To store English words, one method is to use linked lists and store a word letter by letter. ...

  9. angularjs中下拉框select option默认值

    1.问题说明: option ng-repeat多空白项 2.解决方案: html: <ion-view hide-nav-bar="true"> <ion-co ...

  10. linux上hadoop2.4.0安装配置

    1 环境准备 安装java-1.6(jdk) 安装ssh 1.1 安装jdk (1)下载安装jdk 在/usr/lib下创建java文件夹,输入命令: cd /usr/lib mkdir java 输 ...