【题解】刺杀大使

【题解】刺杀大使

P1902 刺杀大使

Solution:二分答案+搜索

分析

既然是求最大值最小,容易想到二分答案,具体就是二分从第一行走到最后一行经过的最大值(假设为mid),用dfs检验,即只走小于等于mid的格子,看是否能到达最后一行
而这道题最有意思的是,vis数组在回溯时无需清空
为什么呢?因为我们关注的是可行性,如果第一次访问到一个点它无法到达最后一行,那么下一次换条路重新经过它,它依然无法到达最后一行
你可能会说可这两次访问的状态实际是不一样的(即vis数组),但你再想想,如果第二次访问这个点,存在一个解需要经过第一次访问中vis已经标记过的点的话,那么这个解一定可以在访问这个"vis已经标记过的点"的时候算出
综上所述,vis数组在回溯时无需清空

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;

inline int read()
{
	register int x=0,w=1;
	register char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if(ch=='-'){ch=getchar();w=-1;}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*w;
}
const int dirx[4]={-1,1,0,0},diry[4]={0,0,-1,1};
//queue<int>qx,qy;
int n,m,mid,f;
int mp[1005][1005],vis[1005][1005];
void dfs(int x,int y)
{
	if(f==1) return ;
	if(x==m) {
		f=1;
		return ;
	}
	for(int i=0;i<4;++i)
	{
		int xx=x+dirx[i],yy=y+diry[i];
		if(xx<1||yy<1||xx>n||yy>m) continue;
		if(vis[xx][yy]||mp[xx][yy]>mid) continue;
		vis[xx][yy]=1;
		dfs(xx,yy);
	}
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;++i)
      for(int j=1;j<=m;++j)
        mp[i][j]=read();
    int l=0,r=1005;
    while(l+1<r)
    {
    	memset(vis,0,sizeof vis);
    	mid=l+r>>1;
    	f=0;
		dfs(1,1);
		if(f) r=mid;
		else l=mid;
	}
	cout<<r<<endl;
	return 0;
}
上一篇:云电脑直播简单指南


下一篇:迷宫问题