主页面: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. PHP socket 编程中的超时设置

    PHP socket 编程中的超时设置.网上找了半天也没找到.贴出来分享之:设置$socket 发送超时1秒,接收超时3秒: $socket = socket_create(AF_INET,SOCK_ ...

  2. Linux服务器性能分汇总

    工具使用: vmstat 查看cpu时间.内存.IO的情况. 参考:http://linuxcommand.org/man_pages/vmstat8.html 基本用法: [root@root ~] ...

  3. ElasticSearch API 之 GET

    GET API是Elasticsearch中常用的操作,一般用于验证文档是否存在:或者执行CURD中的文档查询.与检索不同的是,GET查询是实时查询,可以实时查询到索引结果.而检索则是需要经过处理才能 ...

  4. echarts3样例

    <script type="text/javascript" src="echarts.min.js"></script> <di ...

  5. spl_autoload_register() && __autoload函数

    一.__autoload 这是一个自动加载函数,在PHP5中,当我们实例化一个未定义的类时,就会触发此函数. 在index.php中,由于没有包含test.class.php,在实例化printit时 ...

  6. Java 并发编程中使用 ReentrantLock 替代 synchronized 关键字原语

    Java 5 引入的 Concurrent 并发库软件包中,提供了 ReentrantLock 可重入同步锁,用来替代 synchronized 关键字原语,并可提供更好的性能,以及更强大的功能.使用 ...

  7. poj1149最大流经典构图神题

    题意:n个顾客依次来买猪,有n个猪房,每个顾客每次可以开若干个房子,买完时,店主可以调整这位顾客 开的猪房里的猪,共m个猪房,每个猪房有若干猪,求最多能卖多少猪. 构图思想:顾客有先后,每个人想要的猪 ...

  8. Netty构建游戏服务器(一)--基本概念与原理

    一,Netty是什么 1,Netty是由 JBOSS提供的一个 java开源框架. 2,Netty是JAR包,一般使用ALL-IN-ONE的JAR包就可以开发了. 3,Netty不需要运行在Tomca ...

  9. python的__name__和dir()属性

    1.__name__属性 一个模块被另一个程序第一次引入时,其主程序将运行.如果我们想在模块被引入时,模块中的某一程序块不执行,我们可以用__name__属性来使该程序块仅在该模块自身运行时执行.示例 ...

  10. CODEVS_1227 方格取数2 网络流 最小费用流 拆点

    原题链接:http://codevs.cn/problem/1227/ 题目描述 Description 给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1, ...