首页 > 其他分享 >[蓝桥杯 2022 国 A] 环境治理(二分 + 弗洛伊德)

[蓝桥杯 2022 国 A] 环境治理(二分 + 弗洛伊德)

时间:2024-04-05 14:04:50浏览次数:30  
标签:tmp int 灰尘 ++ mid 蓝桥 环境治理 2022 ans

        通过题目描述,我们得知如果枚举所有的天数,就不会通过所有的样例,因此我们可以通过二分来列举符合要求的天数,并且我们知道两个城市之间衡量的灰尘度标准就是灰尘度总和最小的那一段路径,也就是说我们需要寻找到权值和最低的那条路径,而我们知道每两个点之间都有路径可走,因此我们可以用弗洛伊德算法来寻找最小的灰尘度路径,而弗洛伊德算法在本题中应用就是以每个点为中间点,寻找两点直通和两点之间多走中间点的两条路径中最小灰尘度的那种情况,最后再进行P值计算,将P与Q的比较值作为二分算法的依据,需要注意的是,如果一直没有合适的答案,就输出-1,也就是说check函数一直返回false,我们可以用ans = -1来存储答案,当r更新的时候,将ans同步更新成r的值,因此如果没有满足要求的天数,自然就会输出-1。

上代码

#include<iostream>
#include<cstring>
#include<algorithm>
#define int long long

using namespace std;

int n, Q; 
const int N = 1e2 + 10;
int d[N][N];//i到j的灰尘度
int limit[N][N];//i到j的灰尘度下限 
int tmp[N][N];//备份数组 

bool check(int mid)
{
	for(int i = 0; i < n; i++){
		for(int j = 0; j < n; j++){
			tmp[i][j] = d[i][j];
		}
	}//备份数组,防止修改原数组,导致下次使用时候发生变化 
	for(int i = 0; i < n; i++){
		int val = mid / n;//获取走了val圈
		if(mid % n >= i + 1) val++;
		
		for(int j = 0; j < n; j++){
			tmp[i][j] = max(tmp[i][j] - val * 2, limit[i][j]);//因为前一个点减少灰尘度,下一个点也要减少,因此减少两倍,并且不能小于limit[i][j]因此二者取最大值 
		} 
	}
	for(int k = 0; k < n; k++){//以k为中间点,寻找最短路径(最小灰尘度) 
		for(int i = 0; i < n; i++){
			for(int j = 0; j < n; j++){
				if(tmp[i][j] > tmp[i][k] + tmp[k][j]){
					tmp[i][j] = tmp[i][k] + tmp[k][j];
				}//如果当前的灰尘度小于以k为中间点的路径的灰尘度,就更新当前灰尘度 
			}
		}
	} 
	int sum = 0;
	for(int i = 0; i < n; i++){
		for(int j = 0; j < n; j++){
			sum += tmp[i][j];//求当前指标P 
		}
	}
	return sum <= Q;//如果当前指标P小于等于Q说明满足条件,反之就是不满足 
} 

signed main(void)
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	
	cin >> n >> Q;
	for(int i = 0; i < n; i++){
		for(int j = 0; j < n; j++){
			cin >> d[i][j];
		}
	}
	for(int i = 0; i < n; i++){
		for(int j = 0; j < n; j++){
			cin >> limit[i][j];
		} 
	}
	int l = 0, r = 1e18;
	int ans = -1;//因为可能会有一种情况导致无法达标,如果无法达标说明r无法更新,因此可以用ans取代l进行输出,如果一直不达标就会输出-1 
	while(l < r){
		int mid = (l + r) / 2;
		if(check(mid)){
			r = mid;//如果当前mid已经满足条件,就将r更新
			ans = r;//更新r同时更新ans 
		} 
		else l = mid + 1;//如果不满足条件,就将l更新 
	}
	cout << ans << endl;
	
	return 0;
}

标签:tmp,int,灰尘,++,mid,蓝桥,环境治理,2022,ans
From: https://blog.csdn.net/2302_81473103/article/details/137385133

相关文章

  • 【蓝桥杯选拔赛真题56】C++求位数 第十四届蓝桥杯青少年创意编程大赛 算法思维 C++编
    目录C++求位数一、题目要求1、编程实现2、输入输出二、算法分析三、程序编写四、程序说明五、运行结果六、考点分析七、推荐资料C++求位数第十四届蓝桥杯青少年创意编程大赛C++选拔赛真题一、题目要求1、编程实现给定一个正整数N(1<N<10^8),输出N为几位数2、......
  • PYTHON蓝桥杯——每日一练(简单题)
    题目查找整数给出一个包含n个整数的数列,问整数a在数列中的第一次出现是第几个。输入格式第一行包含一个整数n。第二行包含n个非负整数,为给定的数列,数列中的每个数都不大于10000。第三行包含一个整数a,为待查找的数。输出格式如果a在数列中出现了,输出它第一次出现的位置(......
  • 蓝桥杯第十三届单片机省赛真题(IAP15F2K61S2)
    一、题目二、题目分析1、难点(笔者个人认为)(1)s17按键短按和长按的设置不同,界面不同s17短按在参数界面需要把温度参数-1;s17长按在时间界面需要显示分,秒界面;所以笔者这里把两个数码管显示分两个函数voidNixie_Show()//数码管显示函数{ Nixie_pos_num(1,16); Nixie_po......
  • 第十四届蓝桥杯单片机省赛真题
    逻辑部分纯手写简单零基础模板套用即可main.c#include"smg.h"#include"key.h"#include"led.h"#include"iic.h"#include"onewire.h"#include"ds1302.h"#include"timer.h"#include"uart.h"#i......
  • 2022蓝桥杯大赛软件类国赛真题 卡牌
    importjava.util.Scanner;publicclassMain{staticfinalintN=200005;staticlongn,m;staticint[]a=newint[N];staticint[]b=newint[N];publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in......
  • 第十四届蓝桥杯B组c/c++第五题接龙数列
    动态规划  接龙数列我打眼一看感觉得用栈stack,取出首位和末位全都入栈,每次弹出栈顶,获取此时的栈顶并弹出和下一个栈顶比较。整了老半天发现不行,原来是我脑子瓦特了。虽然没有用栈解决这道问题,但是,栈和队列都是非常重要的只是,不了解的同学们可以去学习一下,下面有传送门。......
  • 蓝桥杯算法题:开心
    https://www.lanqiao.cn/problems/3824/learningeg:n=1234,k=2可以简单的列出这些选项:●1+2+34●1+23+4●12+3+4利用DFS和回溯的思想,程序推导如下:将n分成左右两部分,l表示left左侧的值,r表示right右侧的值。先将l加入res,再将r作为新的n......
  • 蓝桥杯填九宫幻方
    通过回溯算法对未输入得数字进行全排列后,依次填入格子,判断是否符合条件。可以更改幻方的大小,来填充任意幻方#include<stdio.h>#include<stdlib.h>#include<stdbool.h>intboard[3][3];//保存输入的幻方intans[3][3][3];//填充后符合条件的幻方inttmp[3][3];//幻方......
  • 2022CSP-J组真题 2.解密
    线上OJ:https://www.luogu.com.cn/problem/P8814核心思想:对本题先进行数学公式推导已知ed=(......
  • 蓝桥杯——翻硬币
    题目小明正在玩一个"翻硬币"的游戏。桌上放着排成一排的若干硬币。我们用*表示正面,用o表示反面(是小写字母,不是零)。比如,可能情形是:**oo***oooo;如果同时翻转左边的两个硬币,则变为:oooo***oooo。现在小明的问题是:如果已知了初始状态和要达到的目标状态每次只能同时翻转......