【BZOJ】1656:[Usaco2006 Jan]The Grove 树木(bfs+特殊的技巧)
http://www.lydsy.com/JudgeOnline/problem.php?id=1656
神bfs!
我们知道,我们要绕这个联通的树林一圈。
那么,我们想,怎么才能让我们的bfs绕一个圈做bfs呢
我们可以这样:从联通的任意边界点引一条交边界的射线。
为什么呢?因为这样当我们的bfs到这条射线时,我们可以不向射线拓展!
可是我们考虑的是绕一个圈,那么我们要考虑从另一个放向到达射线的情况(即饶了一圈后到射线我们要考虑拓展)

这样我们就能保证绕了联通块一圈,然后是最短距离
具体细节看代码
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << #x << " = " << x << endl
#define printarr2(a, b, c) for1(i, 1, b) { for1(j, 1, c) cout << a[i][j] << '\t'; cout << endl; }
#define printarr1(a, b) for1(i, 1, b) cout << a[i] << '\t'; cout << endl
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; } const int N=60, Q=N*N*10, dx[]={-1, 1, 0, 0, -1, 1, -1, 1}, dy[]={0, 0, -1, 1, -1, -1, 1, 1};
int a[N][N], line[N][N], f[2][N][N], n, m, front, tail, flag, x, y, X, Y;
struct dat { int x, y, f; }q[Q]; int main() {
read(n); read(m);
for1(i, 1, n) for1(j, 1, m) {
char ch=getchar(); while(ch!='.'&&ch!='X'&&ch!='*') ch=getchar();
if(ch=='X') a[i][j]=1, x=i, y=j;
else if(ch=='*') X=i, Y=j;
}
for1(i, 1, n) if(i+x<=n) line[i+x][y]=1; else break;
q[tail].x=X, q[tail].y=Y, q[tail++].f=0;
while(front!=tail) {
dat &t=q[front++]; if(front==Q) front=0;
x=t.x, y=t.y, flag=t.f;
rep(i, 8) {
int fx=dx[i]+x, fy=dy[i]+y;
if(fx<0 || fy<0 || fx>n || fy>m || a[fx][fy]) continue;
if((line[x][y] || line[fx][fy]) && fy<=y) continue; //当前在射线上或下一个点是射线上时(即从右向左),不能向左拓展
if(line[fx][fy] && !f[1][fx][fy]) { //当这是从射线左边向射线过来时,更新上的点
f[1][fx][fy]=f[flag][x][y]+1;
q[tail].x=fx, q[tail].y=fy, q[tail++].f=1; if(tail==Q) tail=0;
}
else if(!f[flag][fx][fy]) { //继承饶了一圈后的距离向四周拓展
f[flag][fx][fy]=f[flag][x][y]+1;
q[tail].x=fx, q[tail].y=fy, q[tail++].f=flag; if(tail==Q) tail=0;
}
}
}
print(f[1][X][Y]);
return 0;
}
Description
The pasture contains a small, contiguous grove of trees that has no 'holes' in the middle of the it. Bessie wonders: how far is it to walk around that grove and get back to my starting position? She's just sure there is a way to do it by going from her start location to successive locations by walking horizontally, vertically, or diagonally and counting each move as a single step. Just looking at it, she doesn't think you could pass 'through' the grove on a tricky diagonal. Your job is to calculate the minimum number of steps she must take. Happily, Bessie lives on a simple world where the pasture is represented by a grid with R rows and C columns (1 <= R <= 50, 1 <= C <= 50). Here's a typical example where '.' is pasture (which Bessie may traverse), 'X' is the grove of trees, '*' represents Bessie's start and end position, and '+' marks one shortest path she can walk to circumnavigate the grove (i.e., the answer): ...+... ..+X+.. .+XXX+. ..+XXX+ ..+X..+ ...+++* The path shown is not the only possible shortest path; Bessie might have taken a diagonal step from her start position and achieved a similar length solution. Bessie is happy that she's starting 'outside' the grove instead of in a sort of 'harbor' that could complicate finding the best path.

Input
* Line 1: Two space-separated integers: R and C
* Lines 2..R+1: Line i+1 describes row i with C characters (with no spaces between them).
Output
* Line 1: The single line contains a single integer which is the smallest number of steps required to circumnavigate the grove.
Sample Input
.......
...X...
..XXX..
...XXX.
...X...
......*
Sample Output
【BZOJ】1656:[Usaco2006 Jan]The Grove 树木(bfs+特殊的技巧)的更多相关文章
- BZOJ 1656 [Usaco2006 Jan] The Grove 树木:bfs【射线法】
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1656 题意: 给你一个n*m的地图,'.'表示空地,'X'表示树林,'*'表示起点. 所有 ...
- bzoj:1656 [Usaco2006 Jan] The Grove 树木
Description The pasture contains a small, contiguous grove of trees that has no 'holes' in the middl ...
- bzoj1656: [Usaco2006 Jan] The Grove 树木 (bfs+新姿势)
题目大意:一个n*m的图中,“.”可走,“X”不可走,“*”为起点,问从起点开始绕所有X一圈回到起点最少需要走多少步. 一开始看到这题,自己脑洞了下怎么写,应该是可过,然后跑去看了题解,又学会了一 ...
- 【BZOJ-1656】The Grove 树木 BFS + 射线法
1656: [Usaco2006 Jan] The Grove 树木 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 186 Solved: 118[Su ...
- BZOJ 1718: [Usaco2006 Jan] Redundant Paths 分离的路径( tarjan )
tarjan求边双连通分量, 然后就是一棵树了, 可以各种乱搞... ----------------------------------------------------------------- ...
- bzoj 1654: [Usaco2006 Jan]The Cow Prom 奶牛舞会 -- Tarjan
1654: [Usaco2006 Jan]The Cow Prom 奶牛舞会 Time Limit: 5 Sec Memory Limit: 64 MB Description The N (2 & ...
- BZOJ 1718: [Usaco2006 Jan] Redundant Paths 分离的路径
Description 给出一个无向图,求将他构造成双连通图所需加的最少边数. Sol Tarjan求割边+缩点. 求出割边,然后缩点. 将双连通分量缩成一个点,然后重建图,建出来的就是一棵树,因为每 ...
- bzoj:1654 [Usaco2006 Jan]The Cow Prom 奶牛舞会
Description The N (2 <= N <= 10,000) cows are so excited: it's prom night! They are dressed in ...
- BZOJ——1720: [Usaco2006 Jan]Corral the Cows 奶牛围栏
http://www.lydsy.com/JudgeOnline/problem.php?id=1720 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1 ...
随机推荐
- Fireworks层与蒙版的概念和用法
添加热点也是可以嵌套的 切片工具将自动保存在网页图层,并且可以导出为图像 组合为蒙版就是让一部分图形显示的填充为一幅图片的东西,删除蒙版即可将其转换为一个普通的图层,否则还可以移动位置
- vue 不能监测数组长度变化length的原因
由于 JavaScript 的限制,Vue 不能检测以下变动的数组: 当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue 当你修改数组的长度时,例如: ...
- 【VBA编程】14.操作工作簿对象
[访问工作簿] 对已经打开的工作簿,可以通过使用索引号来访问工作簿,也可以通过名称来访问工作簿 [代码区域] Sub 访问工作簿() Dim counter As Integer counter = ...
- 启动loadrunner 11的controller提示试图执行系统不支持的操作(已解决)
启动loadrunner 11的controller提示试图执行系统不支持的操作 分类: loadrunner 2014-05-12 17:33 532人阅读 评论(0) 收藏 举报 win7旗舰版3 ...
- STL容器分析--queue
queue,顾名思义,是指队列.满足先进先出的原则.
- 如何启动mininet实例上的wireshark图形界面
启动wireshark 要启动mininet实例上的wireshark的图形界面,其实关键点只有两个: 保证宿主机上安装了X11 使用ssh -Y mininet@192.168.56.102 登录进 ...
- 斑马Zebra ZPLII指令集中文说明解释
我们最常用的斑马(Zebra)条码打印机,应用ZPLII命令来控制打印,说明书中有每条指令的详细说明及相关示例,下面是各指令的中文释义: ^A 对Zebra内置点阵字体缩放 ^A(可缩放/点阵字体 ...
- 3. Digit Counts【medium】
Count the number of k's between 0 and n. k can be 0 - 9. Example if n = 12, k = 1 in [0, 1, 2, 3, ...
- spring boot +mybatis+druid 多数据源配置
因为我的工程需要在两个数据库中操作数据,所以要配置两个数据库,我这里没有数据源没有什么主从之分,只是配合多数据源必须要指定一个主数据源,所以我就把 操作相对要对的那个数据库设置为主数据(dataBas ...
- Qt 槽函数的使用
今天在代码中遇到这样一个问题,自己感觉槽和函数都写的没错,但是就是不执行槽函数,因为是一个定时器的使用,即定时时间到了就执行槽函数. SeventhWizardPage::SeventhWizardP ...