题目链接
LCP 33. 蓄水 easy
题目描述
给定 N 个无限容量且初始均空的水缸,每个水缸配有一个水桶用来打水,第 i 个水缸配备的水桶容量记作 b u c k e t [ i ] bucket[i] bucket[i]。小扣有以下两种操作:
- 升级水桶:选择任意一个水桶,使其容量增加为 b u c k e t [ i ] + 1 bucket[i]+1 bucket[i]+1
- 蓄水:将全部水桶接满水,倒入各自对应的水缸
每个水缸对应最低蓄水量记作 v a t [ i ] vat[i] vat[i],返回小扣至少需要多少次操作可以完成所有水缸蓄水要求。
注意:实际蓄水量 达到或超过 最低蓄水量,即完成蓄水要求。
示例 1:
输入:bucket = [1,3], vat = [6,8]
输出:4
解释: 第 1 次操作升级 bucket[0]; 第 2 ~ 4 次操作均选择蓄水,即可完成蓄水要求。
示例 2:
输入:bucket = [9,0,1], vat = [0,2,2]
输出:3
解释: 第 1 次操作均选择升级 bucket[1] 第 2~3 次操作选择蓄水,即可完成蓄水要求。
提示:
- 1 < = b u c k e t . l e n g t h = = v a t . l e n g t h < = 100 1 <= bucket.length == vat.length <= 100 1<=bucket.length==vat.length<=100
- 0 < = b u c k e t [ i ] , v a t [ i ] < = 1 0 4 0 <= bucket[i], vat[i] <= 10^4 0<=bucket[i],vat[i]<=104
解法:贪心
我们注意到 蓄水的次数 其实是固定的。所以我们可以直接枚举 蓄水的次数( m a x k = m a x { v a t [ i ] } maxk = max \{ vat[i] \} maxk=max{vat[i]}),如果我们每次蓄水的量是 1 的话,故装满需要 m a x k maxk maxk 次。
接着我们枚举 k k k ( 1 ≤ k ≤ m a x k 1 \leq k \leq maxk 1≤k≤maxk),在总的蓄水次数为 k k k 的情况下,每一个桶的容量应该是 c = ( v a t [ i ] + k − 1 ) / k c = (vat[i] + k - 1)/k c=(vat[i]+k−1)/k,将 c c c 将去其本来的容量 b u c k e t [ i ] bucket[i] bucket[i] 就是这个桶需要升级的次数 d d d,即 d = m a x { c − b u c k e t [ i ] , 0 } d = max \{c - bucket[i] , 0 \} d=max{c−bucket[i],0}(因为 c − b u c k e t [ i ] c - bucket[i] c−bucket[i] 可能 < 0 <0 <0)。
接着把总的蓄水次数 k k k + 每一个水桶的升级次数 d d d 就是总的操作次数。我们只要取其中的最小值即可。
时间复杂度: O ( n × m a x k ) O(n \times maxk) O(n×maxk)
C++代码:
class Solution {
public:
int storeWater(vector<int>& bucket, vector<int>& vat) {
int maxk = *max_element(vat.begin(),vat.end());
if(maxk == 0) return 0;
int n = bucket.size();
int ans = 1e9;
//k 是总共需要蓄水的次数
for(int k = 1;k <= maxk;k++){
int t = k;
for(int i = 0;i < n;i++){
//c 是当蓄水次数为k的清空下,能够装满水的 bucket[i] 的最小容量
int c = (vat[i] + k - 1) / k;
//c - bucket[i] 就是需要升级水桶的次数,因为可能为负数,所以 max(c - bucket[i],0)
t += max(c - bucket[i] , 0);
}
ans = min(ans,t);
}
return ans;
}
};