题解:P8794 [蓝桥杯 2022 国 A] 环境治理
道路改善天数增长,“出行环境”的值并不会减少,具有单调性,考虑二分最少天数。
看见 \(P=\sum \limits_{i=0}^{n-1} \sum \limits_{j=0}^{n-1} d(i,j)\),是多源最短路,又 \(n \le 100\),尝试 Floyd。
重点在二分的检查函数。定义一个函数(暂时叫 ql),用于计算一个点被清理的次数。清理 \(x\) 天,将其分为 \(x \div n\) 个 \(N\) 与 \(x \bmod n\) 个 \(1\),每个点都会被清理至少 \(x \div N\) 次(它是依次清理的,分配完 \(x \div n\) 个 \(N\)),剩余 \(x \bmod n\) 个 \(1\) 则将分配到点 \(1 \sim (x \bmod n)\)。这 \(x \bmod n\) 个点清理次数就会比其他店多清理 \(1\) 次。
很显然,此时每条边的“灰尘度”为 max(L[i][j] ,D[i][j] - ql(i) - ql(j)
再跑一遍 Floyd,计算每条最短路径的“灰尘度”,累加起来,如果 \(\le Q\),就返回真,否则返回假。
奉上代码:
# include <bits/stdc++.h>
# define ql(num) (x / n + (num <= x % n))
using namespace std;
int n , q , d[110][110] , l[110][110] , dp[110][110];
bool check(int x)
{
int sum = 0;
for(int i = 1 ; i <= n ; i ++)
for(int j = 1 ; j <= n ; j ++)
dp[i][j] = max(l[i][j] , d[i][j] - ql(i) - ql(j));
for(int k = 1 ; k <= n ; k ++)
for(int i = 1 ; i <= n ; i ++)
for(int j = 1 ; j <= n ; j ++)
dp[i][j] = min(dp[i][j] , dp[i][k] + dp[k][j]);
for(int i = 1 ; i <= n ; i ++)
for(int j = 1 ; j <= n ; j ++)
sum += dp[i][j];
if(sum <= q) return 1;
return 0;
}
int main()
{
cin >> n >> q;
for(int i = 1 ; i <= n ; i ++)
for(int j = 1 ; j <= n ; j ++)
cin >> d[i][j];
for(int i = 1 ; i <= n ; i ++)
for(int j = 1 ; j <= n ; j ++)
cin >> l[i][j];
int l = 0 , r = 0x3f3f3f3f;
while(l < r)
{
int mid = l + r >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
if(check(l)) cout << l;
else cout << -1;
return 0;
}
如果你看到这儿,就说明你已经看了我的代码,面向题解编程需要注意以下几点:
-
我直接用 define 弄得函数,如果要写函数还要把清理天数 \(x\) 设为全局变量或传进去。
-
请注意左边界一定要为 \(0\),最开始就可能已经满足条件。
-
请注意像我这样写二分最后要检查一遍,因为有无法满足条件的情况。
-
跑 Floyd 与求和要分开!
我因为这个卡了好久。
题外话:话说怎么 1.82k 通过却只有两篇题解

浙公网安备 33010602011771号