luogu P1519 穿越栅栏 Overfencing
题目描述
描述 农夫John在外面的田野上搭建了一个巨大的用栅栏围成的迷宫。幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口。更幸运的是,他所建造的迷宫是一个“完美的”迷宫:即你能从迷宫中的任意一点找到一条走出迷宫的路。给定迷宫的宽度W(1<=W<=38)及高度H(1<=H<=100)。 2*H+1行,每行2*W+1的字符以下面给出的格式表示一个迷宫。然后计算从迷宫中最“糟糕”的那一个点走出迷宫所需的步数(就是从最“糟糕”的一点,走出迷宫的最少步数)。(即使从这一点以最优的方式走向最靠近的出口,它仍然需要最多的步数)当然了,牛们只会水平或垂直地在X或Y轴上移动,他们从来不走对角线。每移动到一个新的方格算作一步(包括移出迷宫的那一步)这是一个W=5,H=3的迷宫:
+-+-+-+-+-+
| |
+-+ +-+ + +
| | | |
+ +-+-+ + +
| | |
+-+ +-+-+-+
如上图的例子,栅栏的柱子只出现在奇数行或奇数列。每个迷宫只有两个出口。
输入输出格式
输入格式:
第一行: W和H(用空格隔开)
第二行至第2 * H + 1行: 每行2 * W + 1个字符表示迷宫
输出格式:
输出一个单独的整数,表示能保证牛从迷宫中任意一点走出迷宫的最小步数。
输入输出样例
5 3
+-+-+-+-+-+
| |
+-+ +-+ + +
| | | |
+ +-+-+ + +
| | |
+-+ +-+-+-+
9
说明
翻译来自NOCOW
USACO 2.4
刚读完题,感觉挺简单啊,不过研究了一下样例,一脸懵逼,这咋可能?。
经过机房某位 S型 dalao(son)的解读,哦,so ga si nei,吆西吆西,interisting!!!
再次就借花献佛了。
关于的理解题意:
为了便于理解,这里稍微修改一下题目。
奇数行的栅栏(就是由‘+’和‘-’号组成)将其看做一层类似膜结构,一层防护膜(没有厚度),穿越不占距离。
然后看偶数列,这里需要将偶数列和其两侧的‘-’看做一个整体,亦可以理解为忽略偶数列,只考虑奇数列。
这里拿样例图解:

结合上图,对题意理解就没什么问题了。
解题剖析:
1.读入含空格矩阵:
想了半天,试了多种输入方法,最终貌似只有getline(:不会用戳我啊)可以用。
但是在输入时,需要多输入一行,并且第一行和第二行会重复,其他没毛病,最后貌似没啥大碍。
scanf("%d%d",&w,&h);
w=w*+;h=h*+;
for(int i=;i<=h+;i++)getline(cin,a[i]);
读入是这样的,若有某位dalao明白以上出现的情况,希望讨论区不吝赐教。
2.字符矩阵转换数字矩阵
在这里定义一个int型map数组。
map[i][j]表示走到这个点需要消耗的距离(偶数行为0,奇数行有空地的话消耗为1)
在字符矩阵中[i][j]这个点为栅栏,不能走,将map[i][j]定义为2.
注意前边说到,输入字符时会有一行多余,所以在转换时处理一下。
此部分代码为:
for(int i=;i<=h+;i++)
for(int j=;j<w;j++)
{ if(a[i][j]==)
{
if((i-)%==)map[i-][j+]=;
else if((j+)%==)map[i-][j+]=;
else map[i-][j+]=;
}
else map[i-][j+]=;
}
3.初始化:
ans[i][j]数组记录走到 i,j这个点到出口的最近距离,栅栏处直接定义为-1。
void initial()
{
for(int i=;i<=h;i++)
for(int j=;j<=w;j++)
if(map[i][j]==)ans[i][j]=-;
else ans[i][j]=;
}
4.找出出口:
这没啥好说的,四个边找出口(注意经以上过程出口可能为0,可能为1)。
for(int i=;i<=w;i++)if(map[][i]==||map[][i]==)bfs(,i);
for(int i=;i<=w;i++)if(map[h][i]==||map[h][i]==)bfs(h,i);
for(int i=;i<=h;i++)if(map[i][]==||map[i][]==)bfs(i,);
for(int i=;i<=h;i++)if(map[i][w]==||map[i][w]==)bfs(i,w);
5.大搜索
已经处理处每一格的消耗距离,在搜索时,加上就好啦。
两个出口,需要搜索两边所以搜完注意初始化,bool型数组。
bool vis[N][M];
struct ahah{
int x,y;
}str,cur;
queue <ahah> que;
void bfs(int x,int y)
{
ans[x][y]=;
vis[x][y]=;
str.x=x;str.y=y;
que.push(str);
while(!que.empty())
{
cur=que.front();
que.pop() ;
for(int i=;i<;i++)
{
str.x=cur.x+dx[i];
str.y=cur.y+dy[i];
if(map[str.x][str.y]!=&&str.x>=&&str.x<=h
&&str.y>=&&str.y<=w&&!vis[str.x][str.y])
{
ans[str.x][str.y]=min(ans[cur.x][cur.y]+map[str.x][str.y],ans[str.x][str.y]); vis[str.x][str.y]=;
que.push(str);
}
}
}
memset(vis,,sizeof(vis));
}
6.找出最大值
将ans数组循环一遍,找出最大值,输出即可。
完整代码:
/*.........................
作者:Manjusaka
时间:2018/7/11
题目:P1519 Overfencing
..........................*/ #include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
#define N int(100)
#define M int(210)
int dx[]={,,,-},dy[]={,-,,};
string a[N];
int w,h,MAX;
int x[],y[],k;
int map[N][M];
int ans[N][M];
void check();
void _scanf();
void initial();
void bfs(int ,int );
void _scanf()
{
scanf("%d%d",&w,&h);
w=w*+;h=h*+;
for(int i=;i<=h+;i++)getline(cin,a[i]);
for(int i=;i<=h+;i++)
for(int j=;j<w;j++)
{ if(a[i][j]==)
{
if((i-)%==)map[i-][j+]=;
else if((j+)%==)map[i-][j+]=;
else map[i-][j+]=;
}
else map[i-][j+]=;
}
// cout<<"\n";for(int i=1;i<=h;i++){for(int j=1;j<=w;j++){cout<<map[i][j];}cout<<endl;}
check();
}
void check()
{
initial();
for(int i=;i<=w;i++)if(map[][i]==||map[][i]==)bfs(,i);
for(int i=;i<=w;i++)if(map[h][i]==||map[h][i]==)bfs(h,i);
for(int i=;i<=h;i++)if(map[i][]==||map[i][]==)bfs(i,);
for(int i=;i<=h;i++)if(map[i][w]==||map[i][w]==)bfs(i,w);
for(int i=;i<=h;i++)
{
cout<<"\n";
for(int j=;j<=w;j++)
{
printf("%3d",ans[i][j]);
}
}
}
void initial()
{
for(int i=;i<=h;i++)
for(int j=;j<=w;j++)
if(map[i][j]==)ans[i][j]=-;
else ans[i][j]=;
}
bool vis[N][M];
struct ahah{
int x,y;
}str,cur;
queue <ahah> que;
void bfs(int x,int y)
{
ans[x][y]=;
vis[x][y]=;
str.x=x;str.y=y;
que.push(str);
while(!que.empty())
{
cur=que.front();
que.pop() ;
for(int i=;i<;i++)
{
str.x=cur.x+dx[i];
str.y=cur.y+dy[i];
if(map[str.x][str.y]!=&&str.x>=&&str.x<=h
&&str.y>=&&str.y<=w&&!vis[str.x][str.y])
{
ans[str.x][str.y]=min(ans[cur.x][cur.y]+map[str.x][str.y],ans[str.x][str.y]); vis[str.x][str.y]=;
que.push(str);
}
}
}
memset(vis,,sizeof(vis));
}
void _printf()
{
for(int i=;i<=h;i++)
for(int j=;j<=w;j++)
MAX=max(MAX,ans[i][j]);
printf("\n%d",MAX);
}
int main()
{
_scanf();
_printf();
}
求助大佬!!:
按题目要求来说二位数组开到100*200应该完全可以啊,为什么会比RE,求解释。
luogu P1519 穿越栅栏 Overfencing的更多相关文章
- 洛谷P1519 穿越栅栏 Overfencing
P1519 穿越栅栏 Overfencing 69通过 275提交 题目提供者该用户不存在 标签USACO 难度普及/提高- 提交 讨论 题解 最新讨论 USACO是100分,洛谷是20分 为什么 ...
- 【刷题】洛谷 P1519 穿越栅栏 Overfencing
题目描述 描述 农夫John在外面的田野上搭建了一个巨大的用栅栏围成的迷宫.幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口.更幸运的是,他所建造的迷宫是一个“完美的”迷宫:即你能从迷宫中的任意 ...
- 【USACO 2.4.2】穿越栅栏
[描述] 农夫John在外面的田野上搭建了一个巨大的用栅栏围成的迷宫.幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口.更幸运的是,他所建造的迷宫是一个“完美的”迷宫:即你能从迷宫中的任意一点找 ...
- [luogu P2205] [USACO13JAN]画栅栏Painting the Fence
[luogu P2205] [USACO13JAN]画栅栏Painting the Fence 题目描述 Farmer John has devised a brilliant method to p ...
- [Luogu 5465] [LOJ 6435] [PKUSC2018]星际穿越(倍增)
[Luogu 5465] [LOJ 6435] [PKUSC2018]星际穿越(倍增) 题面 n个点的图,点i和[l[i],i)的所有点连双向边.每次询问(l,r,x)表示x到[l,r]的所有点的最短 ...
- 【luogu P2731 骑马修栅栏】 题解
题目链接:https://www.luogu.org/problemnew/show/P2731 这个题是欧拉回路的模板题,那么在这里给出一个hierholzer的做法. 对于求欧拉回路的问题,有Fl ...
- luogu P2731 骑马修栅栏 Riding the Fences
入度为奇数的点,搜他. 最好邻接矩阵... #include<cstdio> #include<iostream> #define R register int using n ...
- 洛谷P2731 骑马修栅栏 [欧拉回路]
题目传送门 骑马修栅栏 题目背景 Farmer John每年有很多栅栏要修理.他总是骑着马穿过每一个栅栏并修复它破损的地方. 题目描述 John是一个与其他农民一样懒的人.他讨厌骑马,因此从来不两次经 ...
- P2731 骑马修栅栏 (欧拉路径)
[题目描述] John是一个与其他农民一样懒的人.他讨厌骑马,因此从来不两次经过一个栅栏.你必须编一个程序,读入栅栏网络的描述,并计算出一条修栅栏的路径,使每个栅栏都恰好被经过一次.John能从任何一 ...
随机推荐
- bzoj 3697: 采药人的路径【点分治】
点分治,设当前处理的块的重心为rt,预处理出每个子树中f[v][0/1]表示组合出.没组合出一对值v的链数(从当前儿子出发的链),能组合出一对v值就是可以有一个休息点 然后对于rt,经过rt且合法的路 ...
- 洛谷P2585 [ZJOI2006]三色二叉树(树形dp)
传送门 设$dp[u][i]$表示点$u$颜色为$i$时最多(最少)的绿点个数(这里用$0$表示绿点) 然后直接用树形dp就可以了 记得把情况讨论清楚 //minamoto #include<b ...
- 【EXCEL终极总结分享】基于NPOI扩展封装的简易操作工具类库(简单灵活易用,支持导出、导入、上传等常见操作)
对于EXCEL的导入.导出,我之前已分享过多次,比如: 第一种方案:<我写的一个ExcelHelper通用类,可用于读取或生成数据>这个主要是利用把EXCEL当成一个DB来进行获取数据,导 ...
- (DP)51NOD 1007正整数分组
将一堆正整数分为2组,要求2组的和相差最小. 例如:1 2 3 4 5,将1 2 4分为1组,3 5分为1组,两组和相差1,是所有方案中相差最少的. 输入 第1行:一个数N,N为正整数的数量. 第 ...
- 在img标签上尽量不要使用onerror事件
在img标签上尽量不要使用onerror事件 因为在之前的时候,我在本地对用户头像修改发现,如果图片加载失败, 使用onerror事件去获取一个默认地址的图片虽然这是可行的,但是如果刚好onerror ...
- AJPFX总结jvm运行时内存分布
jvm的运行过程中将java程序运行时数据区分为以下几个部分: (1)程序计数器:存储虚拟机字节码执行的地址 (2)java虚拟机栈:java方法运行时的局部变量表,操作数栈,方法出口等 ( ...
- python中一些函数应用
items将一个字典以列表的形式返回,因为字典是无序的,所以返回的列表也是无序的. 例如:a = {"a":1,"b":2} a.items 就是 a ...
- jquery实现上传图片及图片大小验证、图片预览效果代码
jquery实现上传图片及图片大小验证.图片预览效果代码 jquery实现上传图片及图片大小验证.图片预览效果代码 上传图片验证 */ function submit_upload_picture() ...
- Bundle的用法
一.API文档说明 1.介绍 用于不同Activity之间的数据传递 1.重要方法 clear():清除此Bundle映射中的所有保存的数据. clone():克隆当前Bundle containsK ...
- yum install perl-ExtUtils-MakeMaker
Can't locate ExtUtils/MakeMaker.pm in @INC (@INC contains: /usr/local/lib/perl5 /usr/local/share/per ...