P8794 [蓝桥杯 2022 国 A] 环境治理
题目描述
LQ 国拥有 nnn 个城市,从 000 到 n−1n - 1n−1 编号,这 nnn 个城市两两之间都有且仅有一条双向道路连接,这意味着任意两个城市之间都是可达的。每条道路都有一个属性 DDD,表示这条道路的灰尘度。当从一个城市 A 前往另一个城市 B 时,可能存在多条路线,每条路线的灰尘度定义为这条路线所经过的所有道路的灰尘度之和,LQ 国的人都很讨厌灰尘,所以他们总会优先选择灰尘度最小的路线。
LQ 国很看重居民的出行环境,他们用一个指标 PPP 来衡量 LQ 国的出行环境,PPP 定义为:
P=∑i=0n−1∑j=0n−1d(i,j)P=\sum \limits_{i=0}^{n-1} \sum \limits_{j=0}^{n-1} d(i,j)P=i=0∑n−1j=0∑n−1d(i,j)
其中 d(i,j)d(i,j)d(i,j) 表示城市 iii 到城市 jjj 之间灰尘度最小的路线对应的灰尘度的值。
为了改善出行环境,每个城市都要有所作为,当某个城市进行道路改善时,会将与这个城市直接相连的所有道路的灰尘度都减少 111,但每条道路都有一个灰尘度的下限值 LLL,当灰尘度达到道路的下限值时,无论再怎么改善,道路的灰尘度也不会再减小了。
具体的计划是这样的:
- 第 111 天,000 号城市对与其直接相连的道路环境进行改善;
- 第 222 天,111 号城市对与其直接相连的道路环境进行改善;
……
- 第 nnn 天,n−1n - 1n−1 号城市对与其直接相连的道路环境进行改善;
- 第 n+1n + 1n+1 天,000 号城市对与其直接相连的道路环境进行改善;
- 第 n+2n + 2n+2 天,111 号城市对与其直接相连的道路环境进行改善;
……
LQ 国想要使得 PPP 指标满足 P≤QP \leq QP≤Q。请问最少要经过多少天之后,PPP 指标可以满足 P≤QP \leq QP≤Q。如果在初始时就已经满足条件,则输出 000;如果永远不可能满足,则输出 −1-1−1。
输入格式
输入的第一行包含两个整数 n,Qn, Qn,Q,用一个空格分隔,分别表示城市个数和期望达到的 PPP 指标。
接下来 nnn 行,每行包含 nnn 个整数,相邻两个整数之间用一个空格分隔,其中第 iii 行第 jjj 列的值 Di,j(Di,j=Dj,i,Di,i=0)D_{i,j} (D_{i,j}=D_{j,i},D_{i,i} = 0)Di,j(Di,j=Dj,i,Di,i=0) 表示城市 iii 与城市 jjj 之间直接相连的那条道路的灰尘度。
接下来 nnn 行,每行包含 nnn 个整数,相邻两个整数之间用一个空格分隔,其中第 iii 行第 jjj 列的值 Li,j(Li,j=Lj,i,Li,i=0)L_{i,j} (L_{i,j} = L_{j,i}, L_{i,i} = 0)Li,j(Li,j=Lj,i,Li,i=0) 表示城市 iii 与城市 jjj 之间直接相连的那条道路的灰尘度的下限值。
输出格式
输出一行包含一个整数表示答案。
输入输出样例 #1
输入 #1
3 10
0 2 4
2 0 1
4 1 0
0 2 2
2 0 0
2 0 0
输出 #1
2
说明/提示
【样例说明】
初始时的图如下所示,每条边上的数字表示这条道路的灰尘度:
此时每对顶点之间的灰尘度最小的路线对应的灰尘度为:
- d(0,0)=0,d(0,1)=2,d(0,2)=3d(0, 0) = 0, d(0, 1) = 2, d(0, 2) = 3d(0,0)=0,d(0,1)=2,d(0,2)=3;
- d(1,0)=2,d(1,1)=0,d(1,2)=1d(1, 0) = 2, d(1, 1) = 0, d(1, 2) = 1d(1,0)=2,d(1,1)=0,d(1,2)=1;
- d(2,0)=3,d(2,1)=1,d(2,2)=0d(2, 0) = 3, d(2, 1) = 1, d(2, 2) = 0d(2,0)=3,d(2,1)=1,d(2,2)=0。
初始时的 PPP 指标为 (2+3+1)×2=12(2 + 3 + 1) \times 2 = 12(2+3+1)×2=12,不满足 P≤Q=10P \leq Q = 10P≤Q=10;
第一天,000 号城市进行道路改善,改善后的图示如下:
注意到边 (0,2)(0, 2)(0,2) 的值减小了 111,但 (0,1)(0, 1)(0,1) 并没有减小,因为 L0,1=2L_{0,1} = 2L0,1=2 ,所以 (0,1)(0, 1)(0,1) 的值不可以再减小了。此时每对顶点之间的灰尘度最小的路线对应的灰尘度为:
- d(0,0)=0,d(0,1)=2,d(0,2)=3d(0, 0) = 0, d(0, 1) = 2, d(0, 2) = 3d(0,0)=0,d(0,1)=2,d(0,2)=3,
- d(1,0)=2,d(1,1)=0,d(1,2)=1d(1, 0) = 2, d(1, 1) = 0, d(1, 2) = 1d(1,0)=2,d(1,1)=0,d(1,2)=1,
- d(2,0)=3,d(2,1)=1,d(2,2)=0d(2, 0) = 3, d(2, 1) = 1, d(2, 2) = 0d(2,0)=3,d(2,1)=1,d(2,2)=0。
此时 PPP 仍为 121212。
第二天,1 号城市进行道路改善,改善后的图示如下:
此时每对顶点之间的灰尘度最小的路线对应的灰尘度为:
- d(0,0)=0,d(0,1)=2,d(0,2)=2d(0, 0) = 0, d(0, 1) = 2, d(0, 2) = 2d(0,0)=0,d(0,1)=2,d(0,2)=2,
- d(1,0)=2,d(1,1)=0,d(1,2)=0d(1, 0) = 2, d(1, 1) = 0, d(1, 2) = 0d(1,0)=2,d(1,1)=0,d(1,2)=0,
- d(2,0)=2,d(2,1)=0,d(2,2)=0d(2, 0) = 2, d(2, 1) = 0, d(2, 2) = 0d(2,0)=2,d(2,1)=0,d(2,2)=0。
此时的 PPP 指标为 (2+2)×2=8<Q(2 + 2) \times 2 = 8 < Q(2+2)×2=8<Q,此时已经满足条件。
所以答案是 222。
【评测用例规模与约定】
- 对于 30%30\%30% 的评测用例,1≤n≤101 \leq n \leq 101≤n≤10,0≤Li,j≤Di,j≤100 \leq L_{i,j} \leq D_{i,j} \leq 100≤Li,j≤Di,j≤10;
- 对于 60%60\%60% 的评测用例,1≤n≤501 \leq n \leq 501≤n≤50,0≤Li,j≤Di,j≤1050 \leq L_{i,j} \leq D_{i,j} \leq 10^50≤Li,j≤Di,j≤105;
- 对于所有评测用例,1≤n≤1001 \leq n \leq 1001≤n≤100,0≤Li,j≤Di,j≤1050 \leq L_{i,j} \leq D_{i,j} \leq 10^50≤Li,j≤Di,j≤105,0≤Q≤231−10 \leq Q \leq 2^{31} - 10≤Q≤231−1。
蓝桥杯 2022 国赛 A 组 F 题。
C++实现
#include<bits/stdc++.h>
using namespace std;
#define N 105
#define int long long
#define inf 2002102828
#define mid (l + r >> 1)
#define For(i, j, n) for(int i = j ; i <= n ; ++i)
int n, Q, l, r, ans = inf;
int D[N][N], L[N][N], dis[N][N], down[N];
inline int check(int x){
int t = x / n, P = 0;
For(i, 1, n) For(j, 1, n) dis[i][j] = inf;
For(i, 1, n) dis[i][i] = 0;
For(i, 1, n) down[i] = t;
For(i, 1, x - n * t) ++down[i];
For(i, 1, n) For(j, 1, n) dis[i][j] = max(L[i][j], D[i][j] - down[i] - down[j]);
For(k, 1, n) For(i, 1, n) For(j, 1, n) dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
For(i, 1, n) For(j, 1, n) P += dis[i][j];
if(P <= Q) return 1;
else return 0;
}
signed main(){
scanf("%lld %lld", &n, &Q);
For(i, 1, n) For(j, 1, n) scanf("%lld", &D[i][j]);
For(i, 1, n) For(j, 1, n) scanf("%lld", &L[i][j]);
l = 0, r = inf;
while(l <= r){
if(check(mid)) ans = min(ans, mid), r = mid - 1;
else l = mid + 1;
}
if(ans == inf) printf("-1");
else printf("%lld", ans);
return 0;
}
后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容