题目:
https://www.luogu.com.cn/problem/P1902
解题思路:
一开始理解错误题意,以为要找出所有能到达n层m个房间的路线才能进入大使馆。后来发现只要找到一条能达到n层任意一个房间的路线即可进入大使馆,n层房间之间是互通的,达到其中一个就能到达其他任意房间。
题目是求最大代价的最小值。
二分模板 r=mid check函数要保证mid的最大代价,即路线中的代价都小于等于mid。
dfs求路径:
!!!特别注意:本题目中的dfs不需要恢复现场,否则超时。(注释部分)
对于同一个点,扩展顺序相同,扩展过一次无需再扩展下一次,因为扩展后的路径是固定的,不恢复现场,可有效防止反复无用扩展。同一个点扩展之后不能到达n层,再扩展也不能到达n层。
check函数里面注意flag置零:
完整代码:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
typedef long long LL;
using namespace std;
const int N = 200010;
int n,m;
int p[1010][1010];
int flagg ;
int flag[1010][1010];
//最大值的最小
int my[4]={0,0,1,-1};
int mx[4]={1,-1,0,0};
void dfs(int x, int y,int maxx){
if( x == n ) {
flagg = 1 ;
return ;
}
for(int i=0;i<4;i++){
int tx = x + mx[i];
int ty = y + my[i];
if(tx < 1 || ty < 1 || ty > m || tx > n || p[tx][ty] > maxx || flag[tx][ty] ) continue ;
flag[tx][ty] = 1;
dfs(tx,ty,maxx);
// flag[tx][ty] = 0;
if(flagg) break;
}
if(flagg) return ;
}
int check(int x){ //保证x的最大值
flagg = 0;
memset(flag , 0 ,sizeof flag);
dfs(1,1,x);
if(flagg) return 1;
else return 0;
}
int main(){
cin >> n >> m;
int rr=-INF;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin >> p[i][j];
rr = max(rr,p[i][j]);
}
}
int ll = 0;
while( ll+1 < rr){
int mid = ll + rr >> 1;
if(check(mid)) rr = mid;
else ll = mid;
// cout << "***" << mid << " " << check(mid) <<" " << endl;
}
cout << rr ;
// cout << check(1);
return 0;
}