暴力方法是把所有路径全部跑一遍,现在只考虑((0, 0))位置的门分别走向第n - 1行的所有门的路径,假设只向上向右走,那么(0, 0)到(n - 1, k)的路径条数为(C_{n}^{k}),所以从(0, 0)到第n - 1行所有的门的路径条数总和为(C_{n}^{0} + C_{n}^{1} + ... + C_{n}^{m - 1}),极限情况下总和为(C_{1000}^{0} + C_{1000}^{1} + ... + C_{1000}^{999} = 2^{1000} - 1),但是这个数字一定比真正的总路径条数小,因为没有向下走,回头啥的的路径,所以没法用暴力
思路:二分答案x,并且通过bfs检查能否找到这样一条路径使得路径上的最大值满足≤x,如果能找到这条路径,那么说明所有比x大的值都能够找到这样一条路径,所以答案有二段性,因为是整数二分,所以一定能够找到x的最小值使得找到一条路径使得路径上的最大值=x
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N = 1010;
#define PII pair<int, int>
#define x first
#define y second
int g[N][N], st[N][N];
int n, m;
int dx[] = {0, 0, 1, -1}, dy[] = {-1, 1, 0, 0};
int check(int val){
memset(st, 0, sizeof st);
queue<PII> q;
for(int i = 0; i < m; i ++){
if(st[1][i] == 0 && g[1][i] <= val){
st[0][i] = 1;
q.push({0, i});
while(q.size()){
PII h = q.front();
q.pop();
for(int j = 0; j < 4; j ++){
int x = h.x + dx[j], y = h.y + dy[j];
if(x < 0 || x >= n || y < 0 || y >= m || st[x][y] || g[x][y] > val) continue;
st[x][y] = 1;
q.push({x, y});
if(x == n - 2) return 1;
}
}
}
}
return 0;
}
int main(){
cin >> n >> m;
for(int i = 0; i < n; i ++)
for(int j = 0; j < m; j ++)
cin >> g[i][j];
int l = 0, r = 1000;
while(l < r){
int mid = l + r >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout << l << endl;
return 0;
}