第十三届蓝桥杯Java、C++、Python组国赛真题——环境治理(三语言AC)
创始人
2024-03-30 11:26:26
0

目录

  • 1.环境治理
    • 1.问题描述
    • 2.输入格式
    • 3.输出格式
    • 4.样例输入
    • 5.样例输出
    • 6.数据范围
    • 7.原题链接
  • 2.解题思路
  • 3.模板代码
    • C++
    • Java
    • python

1.环境治理

1.问题描述

LQ 国拥有 nnn 个城市, 从 0 到 n−1n-1n−1 编号, 这 nnn 个城市两两之间都有且仅有 一条双向道路连接, 这意味着任意两个城市之间都是可达的。每条道路都有一 个属性 DDD, 表示这条道路的灰尘度。当从一个城市 AAA 前往另一个城市 BBB 时, 可 能存在多条路线, 每条路线的灰尘度定义为这条路线所经过的所有道路的灰尘 度之和, LQ 国的人都很讨厌灰尘, 所以他们总会优先选择灰尘度最小的路线。

LQ 国很看重居民的出行环境, 他们用一个指标 PPP 来衡量 LQ 国的出行环 境, PPP 定义为:

P=∑i=0n−1∑j=0n−1d(i,j)P=\sum_{i=0}^{n-1} \sum_{j=0}^{n-1} d(i, j) P=i=0∑n−1​j=0∑n−1​d(i,j)

其中 d(i,j)d(i, j)d(i,j) 表示城市 iii 到城市 jjj 之间灰尘度最小的路线对应的灰尘度的值。 为了改善出行环境, 每个城市都要有所作为, 当某个城市进行道路改善时, 会将与这个城市直接相连的所有道路的灰尘度都减少 1 , 但每条道路都有一个 灰尘度的下限值 LLL, 当灰尘度达到道路的下限值时, 无论再怎么改善, 道路的 灰尘度也不会再减小了。

具体的计划是这样的:

第 1 天, 0 号城市对与其直接相连的道路环境进行改善;

第 2 天, 1 号城市对与其直接相连的道路环境进行改善;

⋯\cdots⋯

第 nnn 天, n−1n-1n−1 号城市对与其直接相连的道路环境进行改善;

第 n+1n+1n+1 天, 0 号城市对与其直接相连的道路环境进行改善;

第 n+2n+2n+2 天, 1 号城市对与其直接相连的道路环境进行改善;

LQ 国想要使得 PPP 指标满足 P≤QP \leq QP≤Q 。请问最少要经过多少天之后, PPP 指标 可以满足 P≤QP \leq QP≤Q 。如果在初始时就已经满足条件, 则输出 0 ; 如果永远不可能 满足, 则输出 −1-1−1 。

2.输入格式

输入的第一行包含两个整数 n,Qn,Qn,Q, 用一个空格分隔, 分别表示城市个数和 期望达到的 PPP 指标。

接下来 nnn 行, 每行包含 nnn 个整数, 相邻两个整数之间用一个空格分隔, 其 中第 iii 行第 jjj 列的值 Dij(Dij=Dji,Dii=0)D_{i j}\left(D_{i j}=D_{j i}, D_{i i}=0\right)Dij​(Dij​=Dji​,Dii​=0) 表示城市 iii 与城市 jjj 之间直接相连 的那条道路的灰尘度。

接下来 nnn 行, 每行包含 nnn 个整数, 相邻两个整数之间用一个空格分隔, 其 中第 iii 行第 jjj 列的值 Lij(Lij=Lji,Lii=0)L_{i j}\left(L_{i j}=L_{j i}, L_{i i}=0\right)Lij​(Lij​=Lji​,Lii​=0) 表示城市 iii 与城市 jjj 之间直接相连的 那条道路的灰尘度的下限值。

3.输出格式

输出一行包含一个整数表示答条。

4.样例输入

3 10
0 2 4
2 0 1
4 1 0
0 2 2
2 0 0
2 0 0

5.样例输出

2

6.数据范围

1≤n≤100,0≤Lij≤Dij≤100000,0≤Q≤231−11≤n≤100,0≤Lij ≤Dij ≤100000,0≤Q≤2^{31} −11≤n≤100,0≤Lij≤Dij≤100000,0≤Q≤231−1 。

7.原题链接

环境治理

2.解题思路

首先,对于求解P指的公式,我们要清楚,是每个点到其他所有点的最短路径之和相加,这种涉及到任意两点的最短路,加上 nnn 的最大范围只有100,很明显我们需要想到Floyd算法求任意两点的最短路。

我们并没有一个直观的算法直接求得答案,所以,我们考虑二分答案。 如果改善x天是符合要求的,那么大于x的天数也一定符合,但小于x的天数不一定,所以满足二段性,我们可以二分。

我们用g[][]记录初始道路的灰尘度,m[][]记录每条道路的最低灰尘度,f[][]记录的是在改善x天后的每条道路的环境。这样我们就可以使用二分+Floyd的做法得到答案。

当然这里有一些需要注意的细节问题,当我们改变f[i][j]的值时,相应的也要改变f[j][i]的值,因为任意两点只存在一条双向道路,所以这两个状态应该表示的是同一条道路。每次check时,别忘记将f[][]重置回g[][],再去减去对于的天数。floyd函数每次跑完后,计算并返回此时的P值。

最开始时我们可以判断每条道路都是最低复杂度的情况下,计算出来的P是否大于Q,如果大于说明肯定无解,直接返回-1即可。二分对于r的上限也需要注意,最多100个点,每个点最大1e5,所以理论上我们只要开到大于1e7以上就不会有问题,否则样例过大时可能会出错。

时间复杂度:O(n3log(n∗m))O(n^3log(n*m))O(n3log(n∗m))

3.模板代码

C++

#include
using namespace std;
typedef long long LL;
const int N=110;LL g[N][N];
LL m[N][N];
LL f[N][N];
LL n,q;
LL floyd()
{LL a=0;for (int k = 1; k <= n; k ++ )for (int i = 1; i <= n; i ++ )for (int j = 1; j <= n; j ++ )f[i][j] = min(f[i][j], f[i][k] + f[k][j]);for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)a+=f[i][j];return a;
}
//改善X天
bool check(LL x){memcpy(f,g,sizeof(g));LL h=x/n;LL s=x%n;for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){if(i==j) continue;if(i<=s) f[i][j]=max(m[i][j],f[i][j]-h-1);else f[i][j]=max(m[i][j],f[i][j]-h);f[j][i]=f[i][j];}}return floyd()<=q;
}
void solve()
{cin>>n>>q;for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){cin>>g[i][j];}}for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){cin>>m[i][j];f[i][j]=m[i][j];}}if(floyd()>q){cout<<-1<int mid=l+r>>1;if(check(mid)) r=mid;else l=mid+1;}cout<solve();return 0;
}

Java

import java.io.*;public class Main {static int N=110;static long[][] g=new long[N][N],m=new long[N][N],f=new long[N][N];static long n,q;static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));static PrintWriter  out=new PrintWriter(new OutputStreamWriter(System.out));public static void main(String[] args) throws IOException {String[] s=br.readLine().split(" ");n=Long.parseLong(s[0]);q=Long.parseLong(s[1]);for(int i=1;i<=n;++i){s=br.readLine().split(" ");for(int j=1;j<=n;++j){g[i][j]=Long.parseLong(s[j-1]);}}for(int i=1;i<=n;++i){s=br.readLine().split(" ");for(int j=1;j<=n;++j){m[i][j]=Long.parseLong(s[j-1]);f[i][j]=m[i][j];}}if(floyd()>q){out.println(-1);out.flush();return;}long l=0,r=1000000000;while(llong mid=l+r>>1;if(check(mid)) r=mid;else l=mid+1;}out.println(r);out.flush();}static long floyd(){long a=0;for (int k = 1; k <= n; k ++ )for (int i = 1; i <= n; i ++ )for (int j = 1; j <= n; j ++ )f[i][j] =Math.min(f[i][j], f[i][k] + f[k][j]);for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)a+=f[i][j];return a;}static boolean check(long x){for(int i=1;i<=n;++i){for(int j=1;j<=n;++j) f[i][j]=g[i][j];}long h=x/n;long s=x%n;for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){if(i==j) continue;if(i<=s) f[i][j]=Math.max(m[i][j],f[i][j]-h-1);else f[i][j]=Math.max(m[i][j],f[i][j]-h);f[j][i]=f[i][j];}}return floyd()<=q;}
}

python

import copy
N=110
g=[[0]*N for i in range(N)]
m=[[0]*N for i in range(N)]
f=[[0]*N for i in range(N)]
n,q=map(int,input().split())
def floyd(f):a=0for k in range(1,n+1):for i in range(1,n+1):for j in range(1,n+1):f[i][j]=min(f[i][j],f[i][k]+f[k][j])for i in range(1,n+1):for j in range(1,n+1):a=a+f[i][j]return a
def check(x,g):f=copy.deepcopy(g)h=x//ns=x%nfor i in range(1,n+1):for j in range(1,n+1):if i==j:continueif i<=s:f[i][j]=max(m[i][j],f[i][j]-h-1)else:f[i][j]=max(m[i][j],f[i][j]-h)f[j][i]=f[i][j]return  floyd(f)<=qdef solve():for i in range(1,n+1):l=list(map(int,input().split()))for j in range(1,n+1):g[i][j]=l[j-1]#灰尘度for i in range(1,n+1):l = list(map(int, input().split()))for j in range(1,n+1):m[i][j]=l[j-1]#灰尘度的下限值f[i][j]=m[i][j]if floyd(f)>q:print(-1)returnl,r=0,10000000while (l < r):mid=(l+r)>>1if (check(mid,g)):r=midelse:l=mid+1print(r)
solve()

相关内容

热门资讯

嵌入式理论复习题库(期末考试版... 一、填空题15*1=15 1. 要下载并调试 STM32 程序,可采用   ...
OSG三维渲染引擎编程学习之二... 目录 第三章:OSG场景组织 3.6 Transform变换节点 第三章:OSG场景组织 ...
cmake 04 使用 pyt... 本文目标 使用 python 写一个管理 cmake 工程的 cli 程序 参考 Python CL...
Java多线程(二)—— Re... ReentrantLock源码解析 ReentrantLock 是可重入的互斥锁,虽然...
linux shell脚本学习 linux shell脚本学习笔记 文章目录linux shell脚本学习笔记一、脚本入门1.我的第...
【MySQL】第九部分 MyS... 【MySQL】第九部分 MySQL信息函数 文章目录【MySQL】第九部分 MySQL信息函数9....
StarRocks 集群安装部... 下表为规划的集群组件分配 域名starrocks1starrocks2starrocks3组件my...
跨平台freebasic集锦(... 目录dim例子语法一行多个变量共享 dim例子 语法 一行多个变量 dim x as integer...
TypeScript 中文手册... 目录 基础类型 介绍 布尔值 数字 字符串 数组 元组 Tuple 枚举 任意值 空值 Null ...
【蓝桥杯】历届真题 天干地支(... 【资源限制】         内存限制:256.0MB   C/C++...