题目链接
题意:n*m的池塘,k个桥,桥的作用是跳过路径上的一个格子,一个人在第n层(最底层),想要走到最上面,求路径中的最小值的最大值是多少。
思路:用二分来枚举路径上的最小值的最大值,bfs检验。bfs要做的事就是,当前只使用大于等于mid的方块和最多k个小于mid的块(就是最多k个桥),能否从第n层到第1层。
queue<node> q[M]; q[ i ] 的意思是到当前点需要用 i 个桥的点。
之后我们先管Q[ 0 ] 看看只用Q[ 0 ] 能否到达, 在过程中需要用桥的存到Q[ 1 ] 中去。 跑完Q[ 0 ] 再去跑Q[ 1 ] 再跑Q[ 2 ] ...
我们在想一下二分,如果当前check成功(结合代码看一下),说明ans可以变大,l=mid+1,否则r=mid-1;
#include <bits/stdc++.h>
using namespace std;
#define pi 3.1415926
#define X first
#define Y second
#define Ysanqian ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define endl "\n"
#define int long long
#define pb push_back
typedef pair<int, int> PII;
const int N = 1e6 + 6000, M = 1010, inf = 0x3f3f3f3f, mod = 1e9 + 7;
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
struct node
{int x,y;
}t,d;
int g[M][M];
bool st[M][M];
int n,m,k;
int check(int mid)
{queue<node>q[M];memset(st,0,sizeof st);for(int i=1;i<=m;i++){st[n][i]=1;t.x=n,t.y=i;if(g[n][i]<mid)q[1].push(t);else q[0].push(t);}//把最低下的一层压入对列for(int i=0;i<=k;i++)//遍历一下所有可以用到的桥,只有遍历最大桥,才可以判断是否可以到达{while(q[i].size()){t=q[i].front();q[i].pop();if(t.x==1)return 1;for(int j=0;j<4;j++){d.x=t.x+dx[j];d.y=t.y+dy[j];if(d.x<1||d.x>n||d.y<1||d.y>m)continue;int op=i;if(g[d.x][d.y]<mid)op++;if(!st[d.x][d.y]){q[op].push(d);st[d.x][d.y]=1;}}}}return 0;
}
void solve()
{cin>>n>>m>>k;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>g[i][j];int left=0,right=1e9+1,ans=0;while(left<=right){int mid=left+right>>1;if(check(mid)==1){ans=mid;left=mid+1;}elseright=mid-1;}cout<<ans<<endl;
}signed main()
{Ysanqian;int T;T=1;//cin >> T;while (T--)solve();return 0;
}