刺杀大使
题目链接
本蒟蒻自己AC的第一道绿题(T_T)
初学算法,希望大家能给点建议
题目描述
某组织正在策划一起对某大使的刺杀行动。他们来到了使馆,准备完成此次刺杀,要进入使馆首先必须通过使馆前的防御迷阵。
迷阵由 n × m n\times m n×m 个相同的小房间组成,每个房间与相邻四个房间之间有门可通行。在第 n n n 行的 m m m 个房间里有 m m m 个机关,这些机关必须全部打开才可以进入大使馆。而第 1 1 1 行的 m m m 个房间有 m m m 扇向外打开的门,是迷阵的入口。除了第 1 1 1 行和第 n n n 行的房间外,每个房间都被使馆的安保人员安装了激光杀伤装置,将会对进入房间的人造成一定的伤害。第 i i i 行第 j j j 列 造成的伤害值为 p i , j p_{i,j} pi,j(第 1 1 1 行和第 n n n 行的 p p p 值全部为 0 0 0)。
现在某组织打算以最小伤害代价进入迷阵,打开全部机关,显然,他们可以选 择任意多的人从任意的门进入,但必须到达第 n n n 行的每个房间。一个士兵受到的伤害值为他到达某个机关的路径上所有房间的伤害值中的最大值,整个部队受到的伤害值为所有士兵的伤害值中的最大值。现在,这个恐怖组织掌握了迷阵的情况,他们需要提前知道怎么安排士兵的行进路线可以使得整个部队的伤害值最小。
输入格式
第一行有两个整数 n , m n,m n,m,表示迷阵的大小。
接下来 n n n 行,每行 m m m 个数,第 i i i 行第 j j j 列的数表示 p i , j p_{i,j} pi,j。
输出格式
输出一个数,表示最小伤害代价。
样例 #1
样例输入 #1
4 2
0 0
3 5
2 4
0 0
样例输出 #1
3
提示
- 50 % 50\% 50% 的数据, n , m ≤ 100 n,m \leq 100 n,m≤100;
- 100 % 100\% 100% 的数据, n , m ≤ 1000 n,m \leq 1000 n,m≤1000, p i , j ≤ 1000 p_{i,j} \leq 1000 pi,j≤1000。
思路
题目意思就是找到某条路径,使得这条路径上最大的数,是所有路径里面最小的。
BFS+二分(还是二分答案)
取数组里面的最大数和最小数(没必要包含第1行和第n行的0)作为边界就好了
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N = 1001;
int p[N][N],n,m;//p数组存储伤害值
bool st[N][N]; //st数组存储是否遍历过
bool check(int mid){
queue<PII> q;
q.push({1,1}); //初始地点
memset(st,0,sizeof st); //初始化st
st[1][1] = true; //初始点来过
int dx[4] = {1,-1,0,0},dy[4]={0,0,1,-1}; //四个方位
while(q.size()){ //套模板就好了
auto t = q.front();
q.pop();
if(t.first == n) return true;
for(int i=0;i<4;i++){
int a = t.first+dx[i],b=t.second+dy[i];
//不要忘记确保mid是移动过的路径里最大的
if(a>0&&a<=n&&b<=m&&b>0&&p[a][b]<=mid&&!st[a][b]){
q.push({a,b});
st[a][b] = true;
}
}
}
return false; //走不到
}
int main(){
cin >> n >> m;
int l = 1001,r = -1; // l 存最小数 r 存最大数
for(int i = 1;i<=n;i++)
for(int j = 1;j<=m;j++){
scanf("%d",&p[i][j]);
r=max(r,p[i][j]);
if(i!=1&&i!=n)
l=min(l,p[i][j]);
}
l--,r++; //防止出现边界问题
while(l+1<r){
int mid =l+r>>1;
if(check(mid)) r = mid; // mid符合,移动右边界
else l = mid; //不符合移动左边界
}
cout << r; //右边是全部符合的所以输出 r
return 0;
}