题目链接
题意: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;
}
else
right=mid-1;
}
cout<<ans<<endl;
}
signed main()
{
Ysanqian;
int T;
T=1;
//cin >> T;
while (T--)solve();
return 0;
}