洛谷 U86501 趣味擂台
题目背景
(JDFZ)(2019)秋季运动会开始辣!运动会中有一个叫做“趣味擂台”的游戏......
题目描述
游戏内容是这样的:擂台是一个(N imes M)的矩阵。由两支班级队伍参与游戏:攻擂方和守擂方。攻擂方由第一排的任意点出发,每次能向上下左右任一方向行进,经过擂台矩阵到达最后一排。而守擂方会在擂台矩阵除第一排和最后一排的任何一个点布置一个同学守擂,这个同学的强壮程度为(P)。分数核算方式是这样的:攻擂方通过擂台矩阵后,他付出的代价为他走过的路径中最强壮同学的强壮程度,而这个代价越小,证明攻擂方的选择越明智,自然得到的分数也最高。现在,强大的高一 · (6)班即将作为攻擂方参加比赛。(6)班知道守擂方的擂台布置情况(即每个点守擂同学的强壮程度)。作为一个强大的班级,(6)班当然想夺得魁首。所以他派出了班级中的(OIer)(Seaway)和(iamrjj)来解决这个问题,使得班级的得分最多。但他们俩太弱了,所以(Seaway)找到了你,请你编程解决这个问题。
输入格式
第一行有两个整数(N,M),表示擂台的大小。
接下来的(N)行,每行(M)个整数,第(i)行的第(j)个数表示这个位置的同学的强壮程度(P[i] [j])。
输出格式
一个正整数,表示(6)班要付出的最小代价。
样例输入
4 4
0 0 0 0
1 2 3 4
4 3 2 1
0 0 0 0
样例输出
3
提示:
数据范围:
对于50%的数据,有(1le N,Mle 100)。
对于全部的数据,有(1le N,Mle 2000),(P[i] [j]le 1000)。
题解:
二分答案+搜索。
二分表示的是这个最大代价的最小值。搜索是判断是否可行,最后的check环节是用flag变量完成的。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,m,l,r,flag;
int map[1010][1010],v[1010][1010],vis[1010][1010];
int dx[10]={0,0,0,-1,1};
int dy[10]={0,1,-1,0,0};
void check(int x)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(map[i][j]<=x)
vis[i][j]=0;
else
vis[i][j]=1;
}
}
void dfs(int x,int y)
{
if(x==n)
{
flag=1;
return;
}
for(int i=1;i<=4;i++)
{
int xx=x+dx[i];
int yy=y+dy[i];
if(xx>0 && xx<=n && yy>0 && yy<=m)
{
if(v[xx][yy]==0 && vis[xx][yy]==0)
{
v[xx][yy]=1;
dfs(xx,yy);
if(flag==1)
break;
}
}
}
}
int main()
{
//freopen("6.in","r",stdin);
//freopen("6.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&map[i][j]);
r=max(r,map[i][j]);
}
while(l+1<r)
{
int mid=(l+r)>>1;
flag=0;
check(mid);
memset(v,0,sizeof v );
dfs(1,1);
if(flag==1)
r=mid;
else
l=mid;
}
printf("%d",r);
return 0;
}