学C++ ——从入门到入土

攻击路线

  • 算法分析
  • 代码实现

算法分析

题目大意:n*m的矩阵,每个格子上有一个权值。求一条(1,1)到(n,m)的路径,使
路径上权值的最小值最大。
【样列输入】forest.in
2 2
7 5
3 4

【样列输出】forest.out
4
解法:本题原本是可以用SPFA做的,但是由于出题的data是专门卡SPFA的,所以这
题只能二分答案。
二分答案的方法是:
先把所有权值进行排序,找到中间值,进行广搜看中间值是否有资格成为路径上的权
值最小值,如果成立,在右半区间重复上述操作,否则,在左半区间重复上述操作。
二分答案后,它检验的办法之神奇,用广搜检验。 (然而考试的时候直接想的是用深度优先搜索发现标记不了)
时间复杂度为o(nmlog2(nm));
提示:二分答案的时候没有必要排序,可以直接以min(A[1][1],A[N][M])作为下界,
上界可以在读入的时候取个最大值

代码实现

话不多说,直接上代码。

#include
using namespace std;

const int maxn=1005;
int N,M;
int a[maxn][maxn];

const int size=maxn*maxn;
int q[size][2],head,tail;
bool V[maxn][maxn];

void pb(int x,int y){
	q[++tail][0]=x,q[tail][1]=y;
	V[x][y]=true;;
}

bool check(int x){
	const int dir[4][2]={-1,0,1,0,0,1,0,-1};
	memset(V,0,sizeof(V));
	head=tail=0,pb(1,1);
	while(head<tail){
		int sx=q[++head][0],sy=q[head][1];
		for(int i=0;i<4;i++){
			int tx=sx+dir[i][0];
			int ty=sy+dir[i][1];
			if(tx<1||ty<1||tx>N||ty>M) continue;
			if(V[tx][ty]||a[tx][ty]<x) continue;
			pb(tx,ty);
		}
	}
	return V[N][M];
}

int main(){
	scanf("%d%d",&N,&M);
	for(int i=1;i<=N;i++)
		for(int j=1;j<=M;j++)
			scanf("%d",&a[i][j]);
	int ans;
	int lft=-1000000000,rgt=min(a[1][1],a[N][M]),mid;
	while(lft<=rgt){
		mid=(lft+rgt)>>1;
		if(check(mid)) ans=mid,lft=mid+1;else rgt=mid-1;
	}
	printf("%d",ans);
	return 0;
}

总之,这应该能算是二分答案里的一股清流了。

如有不对的地方请大家多多指正,谢谢。

你可能感兴趣的:(二分答案+广搜)