0%

LCP 33. 蓄水

LCP33.蓄水

题目描述:

$N$ 个无限容量的水缸,每个水缸配备一个容量为 $bucket[i]$ 的水桶。有两种操作:

  • 升级水桶:选择一个水桶,容量增加 $1$ 。
  • 蓄水:全部水桶接满水,倒入各自的水缸。

每个水缸有最低的蓄水量 $vat[i]$ ,返回至少需要多少次操作。

数据范围:

$1\le N \le 100;0\le bucket[i],vat[i]\le 10^4$

题解:

可以直接枚举需要倒水的次数,这样的话就可以确定每个水桶需要扩充的容量。假设倒水次数为 $k$ ,则水桶需要扩容至 $(vat[i] - 1) / k + 1$ ,也就是 $\lceil vat[i] / k\rceil$ 。枚举 $k$ 时, $k\in [1, \max(vat[i])]$

也可以使用优先级队列。因为操作次数与需要最多倒水次数的缸有关。因此每次选择次数最多的缸,对桶扩容,使其倒水次数减一,然后加入优先级队列。每次都这样进行,直到无法获得更优的解。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public:
int storeWater(vector<int>& bucket, vector<int>& vat) {
int n = bucket.size(), ans = 1e9, maxx = 0;
for(int i = 0; i < n; ++i)
{
if(vat[i] > maxx) maxx = vat[i];
}
if(maxx == 0) return 0;
int tmp = 0;
for(int k = 1; k <= maxx; ++k)
{
tmp = 0;
for(int i = 0; i < n; ++i)
{
int b_size = (vat[i] - 1) / k + 1;
if(b_size > bucket[i])
{
tmp += b_size - bucket[i];
}
}
ans = min(ans, k + tmp);
}
return ans;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
auto optimize_cpp_stdio = []()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int storeWater(vector<int> &bucket, vector<int> &vat)
{
priority_queue<pair<int, int>> q;
int n = bucket.size(), cnt = 0;
// cnt 是扩容次数
for (int i = 0; i < n; ++i)
{
if (vat[i] == 0)
continue;
if (bucket[i] == 0 && vat[i] != 0)
{
bucket[i]++;
cnt++;
}
int times = (vat[i] - 1) / bucket[i] + 1;
q.push({times, i});
}
int ans = 1e9;
if (q.empty())
return 0;
while (cnt < ans)
{
auto out = q.top();
q.pop();
ans = min(ans, cnt + out.first);
// 扩容至 倒水次数减一
if (out.first == 1)
break;
int b_size = (vat[out.second] - 1) / (out.first - 1) + 1;
cnt += b_size - bucket[out.second];
bucket[out.second] = b_size;
q.push({out.first - 1, out.second});
}
return ans;
}
};