POJ1915Knight Moves(单向BFS + 双向BFS)
单向bfs就是水题
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int Max = + ;
struct Node
{
int x, y;
};
int g[Max][Max];
int vis[Max][Max];
int n, sx, sy, ex, ey;
int gx[] = {-, -, -, -, , , , };
int gy[] = {-, -, , , , , -, -};
bool in_bound(int x, int y)
{
if (x >= && y >= && x < n && y < n)
return true;
return false;
}
int bfs(int sx, int sy)
{
Node node, temp;
node.x = sx;
node.y = sy;
vis[sx][sy] = ;
queue<Node> q;
q.push(node);
while (!q.empty())
{
node = q.front();
q.pop();
if (node.x == ex && node.y == ey)
return vis[ex][ey];
for (int i = ; i < ; i++)
{
int fx = node.x + gx[i];
int fy = node.y + gy[i];
if (in_bound(fx, fy) && vis[fx][fy] > vis[node.x][node.y] + )
{
temp.x = fx;
temp.y = fy;
vis[fx][fy] = vis[node.x][node.y] + ;
q.push(temp);
}
}
}
return -;
}
int main()
{
int test;
scanf("%d", &test);
while (test--)
{
scanf("%d", &n);
scanf("%d%d%d%d", &sx, &sy, &ex, &ey);
memset(vis, INF, sizeof(vis));
printf("%d\n", bfs(sx, sy));
}
return ;
}
单向bfs
做这题主要是学着写双向bfs;
分别从起点和终点开始搜,如果重合即找到
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int Max = + ;
struct Node
{
int x, y;
bool step;
};
// 这个step的意思之前没搞明白,他其实就是指的 在某一步下可以走到点
//开始讲 start.step设为true,因此在只能走一次 8 个点,然后8个点都是第一步走的,然后把最后一个点的step设为true,当你走第二部时候,就是 do { 以这个点扩展 8 步} while ( !current.step) step控制了层数。
int g[Max][Max];
int vis[Max][Max];
int n, sx, sy, ex, ey;
int gx[] = {-, -, -, -, , , , };
int gy[] = {-, -, , , , , -, -};
bool in_bound(int x, int y)
{
if (x >= && y >= && x < n && y < n)
return true;
return false;
}
int bfs()
{
if (sx == ex && sy == ey)
return ;
Node start, finish;
start.x = sx;
start.y = sy;
start.step = true;
finish.x = ex;
finish.y = ey;
finish.step = true;
vis[sx][sy] = ;
vis[ex][ey] = ;
queue<Node> frontSearch;
queue<Node> backSearch;
int fstep = , bstep = ;
frontSearch.push(start);
backSearch.push(finish);
Node current;
while (!frontSearch.empty() || !backSearch.empty())
{
if (!frontSearch.empty())
{
do
{
current = frontSearch.front();
frontSearch.pop();
for (int i = ; i < ; i++)
{
int fx = current.x + gx[i];
int fy = current.y + gy[i];
if (in_bound(fx, fy))
{
if (vis[fx][fy] == )
{
return fstep + bstep + ;
}
if (!vis[fx][fy])
{
vis[fx][fy] = ;
Node temp;
temp.x = fx;
temp.y = fy;
temp.step = false;
frontSearch.push(temp);
}
}
}
}while(current.step == false);
fstep++;
current = frontSearch.front();
frontSearch.pop();
current.step = true; // 为了让最后队列中最后一个数step为true,先将队首拿出来,修改step,然后在入队
frontSearch.push(current);
} if (!backSearch.empty())
{
do
{
current = backSearch.front();
backSearch.pop();
for (int i = ; i < ; i++)
{
int fx = current.x + gx[i];
int fy = current.y + gy[i];
if (in_bound(fx, fy))
{
if (vis[fx][fy] == )
{
return bstep + fstep + ;
}
if (!vis[fx][fy])
{
vis[fx][fy] = ;
Node temp;
temp.x = fx;
temp.y = fy;
temp.step = false;
backSearch.push(temp);
}
}
}
} while(current.step == false);
bstep++;
current = backSearch.front();
backSearch.pop();
current.step = true;
backSearch.push(current);
}
}
return -;
}
int main()
{
int test;
scanf("%d", &test);
while (test--)
{
scanf("%d", &n);
scanf("%d%d%d%d", &sx, &sy, &ex, &ey);
memset(vis, , sizeof(vis));
printf("%d\n", bfs());
}
return ;
}
第二种 双向bfs写法:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int Max = + ;
struct Node
{
int x, y;
bool step;
};
int g[Max][Max];
int fvis[Max][Max], bvis[Max][Max];
int n, sx, sy, ex, ey;
int gx[] = {-, -, -, -, , , , };
int gy[] = {-, -, , , , , -, -};
bool in_bound(int x, int y)
{
if (x >= && y >= && x < n && y < n)
return true;
return false;
}
int bfs()
{
if (sx == ex && sy == ey)
return ;
Node start, finish;
start.x = sx;
start.y = sy;
start.step = true;
finish.x = ex;
finish.y = ey;
finish.step = true;
fvis[sx][sy] = ;
bvis[ex][ey] = ;
queue<Node> frontSearch;
queue<Node> backSearch;
int fstep = , bstep = ;
frontSearch.push(start);
backSearch.push(finish);
Node current;
while (!frontSearch.empty() || !backSearch.empty())
{
int frontSize = (int) frontSearch.size();
while (frontSize--) // 直接将这一个队 全都 拿出来更新,就相当于上一中的step一样,控制搜索的层次
{
current = frontSearch.front();
frontSearch.pop(); for (int i = ; i < ; i++)
{
int fx = current.x + gx[i];
int fy = current.y + gy[i];
if (in_bound(fx, fy))
{
if (bvis[fx][fy] != -) // 如果 倒着搜 已经搜到了,返回
return fvis[current.x][current.y] + + bvis[fx][fy];
if (fvis[fx][fy] == -) //否则正着+1
{
Node temp;
temp.x = fx;
temp.y = fy;
fvis[fx][fy] = fvis[current.x][current.y] + ;
frontSearch.push(temp);
}
}
}
}
int backSize = (int) backSearch.size();
while (backSize--)
{
current = backSearch.front();
backSearch.pop(); for (int i = ; i < ; i++)
{
int fx = current.x + gx[i];
int fy = current.y + gy[i];
if (in_bound(fx, fy))
{
if (fvis[fx][fy] != -)
{
return bvis[current.x][current.y] + + fvis[fx][fy];
}
if (bvis[fx][fy] == -)
{
Node temp;
temp.x = fx;
temp.y = fy;
bvis[fx][fy] = bvis[current.x][current.y] + ;
backSearch.push(temp);
}
}
}
}
}
return -;
}
int main()
{
int test;
scanf("%d", &test);
while (test--)
{
scanf("%d", &n);
scanf("%d%d%d%d", &sx, &sy, &ex, &ey);
memset(fvis, -, sizeof(fvis));
memset(bvis, -, sizeof(bvis));
printf("%d\n", bfs());
}
return ;
}
双向bfs 方法二
POJ1915Knight Moves(单向BFS + 双向BFS)的更多相关文章
- UVa 1601 || POJ 3523 The Morning after Halloween (BFS || 双向BFS && 降维 && 状压)
题意 :w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...
- POJ 3126 Prime Path 解题报告(BFS & 双向BFS)
题目大意:给定一个4位素数,一个目标4位素数.每次变换一位,保证变换后依然是素数,求变换到目标素数的最小步数. 解题报告:直接用最短路. 枚举1000-10000所有素数,如果素数A交换一位可以得到素 ...
- UVA - 1601 The Morning after Halloween (BFS/双向BFS/A*)
题目链接 挺有意思但是代码巨恶心的一道最短路搜索题. 因为图中的结点太多,应当首先考虑把隐式图转化成显式图,即对地图中可以相互连通的点之间连边,建立一个新图(由于每步不需要每个鬼都移动,所以每个点需要 ...
- POJ1915 BFS&双向BFS
俩月前写的普通BFS #include <cstdio> #include <iostream> #include <cstring> #include <q ...
- bfs(双向bfs加三维数组)
http://acm.hdu.edu.cn/showproblem.php?pid=2612 Find a way Time Limit: 3000/1000 MS (Java/Others) ...
- BFS、双向BFS和A*
BFS.双向BFS和A* Table of Contents 1. BFS 2. 双向BFS 3. A*算法 光说不练是无用的.我们从广为人知的POJ 2243这道题谈起:题目大意:给定一个起点和一个 ...
- 双向BFS和启发式搜索的应用
题目链接 P5507 机关 题意简述 有12个旋钮,每个旋钮开始时处于状态 \(1\) ~ \(4\) ,每次操作可以往规定方向转动一个旋钮 (\(1\Rightarrow2\Rightarrow ...
- 洛谷 P1379 八数码难题(map && 双向bfs)
题目传送门 解题思路: 一道bfs,本题最难的一点就是如何储存已经被访问过的状态,如果直接开一个bool数组,空间肯定会炸,所以我们要用另一个数据结构存,STL大法好,用map来存,直接AC. AC代 ...
- POJ 1915-Knight Moves (单向BFS && 双向BFS 比)
主题链接:Knight Moves 题意:8个方向的 马跳式走法 ,已知起点 和终点,求最短路 研究了一下双向BFS,不是非常难,和普通的BFS一样.双向BFS只是是从 起点和终点同一时候開始搜索,可 ...
随机推荐
- ModernUI教程:主题资源引用
已经完成的主题资源列表 提示:请关注Modern UI的开发工作,资源文件可能在演进版本中新增和删除. 资源列表可以去访问原文,原文可复制,该表未改动原文. 查看目录
- nios II--实验4——按键中断软件部分
软件开发 首先,在硬件工程文件夹里面新建一个software的文件夹用于放置软件部分:打开toolsàNios II 11.0 Software Build Tools for Eclipse,需要进 ...
- android中的图片处理
大图片处理 大图片处理是将原来像素高的转换为像素低的图片,比如原来图片是1024*768的,而手机屏幕是800*600的,这时候就需要进行转换.转换的方式很简单就是等比例缩放. package xid ...
- Android开发之补间动画、XML方式定义补间动画
四种补间动画: 1.透明: 2.缩放: 3.位移: 4.旋转: //点击按钮 实现iv 透明的效果 动画 public void click1(View v) { //1.0意味着着完全不透明 0.0 ...
- mysql之旅【第二篇】
创建,修改和删除表 1,创建表: create table 表名(属性名 数据类型 [完整性约束条件], 属性名 数据类型 [完整性约束条件], 属性名 数据类型 [完整性约束 ...
- 进程间通信方式与Binder机制原理
1, Intent隐式意图携带数据 2, AIDL(Binder) 3, 广播BroadCast 4, 内容提供者ContentProvider --------------------------- ...
- HTML常用标签与表格标签
超链接标签: <a href="超链接地址" target="_blank">超链接的文字</a> _blank或new是在新网页中打开 ...
- js学习笔记3---自定义属性
1.自定义属性-----JS可以为任何 HTML元素 添加 任意个 自定义属性 方法:元素.属性 = 属性值 如:aBtn[0].abc = 123; 2.添加索引值,匹配数组 for(i=0; i& ...
- 「c++小学期」实验题目及代码
面向对象编程的C++,和平时做题用的C++还是有差距的.实验的题目都是小题目,就都做一下吧.(没放代码的为要验收的 实验一 简单C++程序设计 1. 猜价格游戏 编写C++程序完成以下功能: (1) ...
- 【CodeForces 697B】Barnicle
对科学计数法表示的数,输出其10进制的形式. c++来做,需要考虑这些细节: 当b==0,d==0时,只输出a. 当不需要补零的情况有两种: 一种是刚好是整数,只输出a(注意1.0e1的情况是输出1) ...