ybtoj 宽搜进阶二分A. 1.最小权值

Posted SSL_ZZL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ybtoj 宽搜进阶二分A. 1.最小权值相关的知识,希望对你有一定的参考价值。

A. 1.最小权值

ybtoj 宽搜进阶 A. 1.最小权值


题面



解题思路

二分,路径上最大的数
宽搜时加上条件,下一个点不能超过mid,就一定能保证这条路的最大值不大于mid
因为二分会不断缩减到正确答案,最后答案路径的最大值一定等于mid

可以重复走,可以发现只要能到第 n 行,那么第 n 行的所有点都可以走到
而且,本来题面也要求了必须要走第 n 行的所有点
但是怎样保证第 n 行的所有点的值,都不大于mid呢?
方法十分简单,只要把初始的最小值范围 l 改大,改成第 n 行的最大值


Code

#include <bits/stdc++.h>
#define N 1010

using namespace std;

const int w[4][2] = -1, 0, 1, 0, 0, -1, 0, 1;
int n, m, a[N][N], v[N][N], l, r, ans;
queue<pair<int, int> > q;

int che(int x, int y) 
	return (x >= 1 && x <= n && y >= 1 && y <= m);


int check(int maxn) 
	while(!q.empty()) q.pop();
	memset(v, 0, sizeof(v));
	
	for(int i = 1; i <= m; i ++)   //第一行所有符合的点都加进去,走到第 n 行的可能性最大,也包含所有可能路径
		if(a[1][i] > maxn) continue;
		v[1][i] = 1, q.push(make_pair(1, i));
	
	
	while(!q.empty()) 
		int x = q.front().first, y = q.front().second;
		q.pop();
		for(int i = 0; i < 4; i ++) 
			int xx = x + w[i][0], yy = y + w[i][1];
			if(!che(xx, yy) || a[xx][yy] > maxn || v[xx][yy]) continue;
			
			if(xx == n) return 1;
			v[xx][yy] = 1;
			q.push(make_pair(xx, yy));
		
	
	return 0;


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]);
		
	for(int i = 1; i <= m; i ++) l = max(l, a[n][i]);  //最小值范围改为第 n 行的最大值
	r = 1e4;
	while(l <= r) 
		int mid = (l + r) >> 1;
		if(check(mid)) 
			ans = mid, r = mid - 1;
		else l = mid + 1;
	
	printf("%d", ans);
 

以上是关于ybtoj 宽搜进阶二分A. 1.最小权值的主要内容,如果未能解决你的问题,请参考以下文章

ybtoj 二分进阶A. 1.喂养宠物

ybtoj 宽搜进阶B. 2.射击问题

ybtoj 字符串进阶A. 1.生日排序

ybtoj 二分进阶DPC. 3.攻击法坛

ybtoj 深搜进阶A. 2.最大费用

ybtoj「基础算法」第1章 递推算法强化训练贪心A. 1.划分数列