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能从任何一 ...
随机推荐
- 如何开始学习Go语言
除了Java.Python和JavaScript之外,如果要开始学习一门新语言的话,我想应该是Go! Go语言正在被越来越多的公司使用.我们公司的后端服务已经全面采用Go语言实现了. 最开始接触Go语 ...
- mq4参考
更新: 2017/05/24 其实也就是照搬文档,主要是用到一个记一个.方便掌握 ----------------------------------------------------------- ...
- 51nod 1050【DP】
思路: 就是先正常的dp一下求一个最大连续子串,然后特殊情况就是sum-最小连续子串.. 比一比谁大谁小就好了 #include <stdio.h> #include <string ...
- oracle错误:1067进程意外终止
oracle错误:1067进程意外终止我Oracle安装完了之后可以运行的 ,过了一段时间不可以了,就上网找了一下,原来是自己的ip已经改变.我一直使用IP地址的. 将D:\oracle\produc ...
- mysql架构解析
架构 mysql是cs架构,在服务端可以启动该mysqld服务,mysqld进程默认监听在tcp:3306.在客户端使用命令行工具mysql或者图形化工具navicat for mysql进行远程连接 ...
- 接口测试postman和Jmeter
接口测试属于功能测试的范畴,一般来说分为两种,一种是程序内部的接口,一种是系统对外的接口. postman测试接口 1. get请求: (1) 直接在浏览器中输入接口地址+?+参数 (2)使用post ...
- YII2修改backend模块报错An Error occurred while handling another error: exception 'yii\base\InvalidRouteException' with message 'Unable to resolve the request "site/error".' in E:\project\demo\vendor\yiisoft
报错内容: 原因:没有修改common/config/bootstrap.php里的别名 修改后:
- 题解报告:hdu 2196 Computer(树形dp)
Problem Description A school bought the first computer some time ago(so this computer's id is 1). Du ...
- HDU 1223 打表 + 大数
http://acm.hdu.edu.cn/showproblem.php?pid=1223 一般遇到这些题,我都是暴力输出前几项,找规律.未果. 然后输出n = 1时候,以A开始,有多少个答案, n ...
- PHP在不同页面间传递Json数据示例代码
gettest.php文件: <?php $value["name"]= urlencode("我的姓名"); $value["pass&quo ...