0%

2735. 收集巧克力

2735.收集巧克力

题目描述:

给你一个长度为 n 、下标从 0 开始的整数数组 nums ,表示收集不同巧克力的成本。每个巧克力都对应一个不同的类型,最初,位于下标 i 的巧克力就对应第 i 个类型。

在一步操作中,你可以用成本 x 执行下述行为:

  • 同时修改所有巧克力的类型,将巧克力的类型 ith 修改为类型 ((i + 1) mod n)th

假设你可以执行任意次操作,请返回收集所有类型巧克力所需的最小成本。

数据范围:

$1\le n \le 1000, 1\le x \le 10^9$

题解:

$n$ 的范围比较小,直接暴力枚举旋转次数,使用 $dp[i][j]$ 表示当前类型 $i$ 旋转 $j$ 次之后收取的最小代价。

这个地方不能加上旋转的共线,因为可能会有多个经过一次旋转之后同时达到了最小代价,如果加上旋转代价的话,这部分就会重复。

后面就直接枚举旋转了多少次,先加上旋转的贡献,然后再加上每个类型的最小代价。

代码:

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
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;

long long minCost(vector<int> &nums, int x)
{
int n = nums.size();
vector<vector<int>> dp(n, vector<int>(n));
long long ans = LLONG_MAX;
// dp[i][j] = dp[i][j - 1],
for (int i = 0; i < n; ++i)
{
dp[i][0] = nums[i];
for (int j = 1; j < n; ++j)
{
dp[i][j] = min(dp[i][j - 1], nums[(i + j) % n]);
}
}
for (int j = 0; j < n; ++j)
{
long long tmp = 1ll * x * j;
for (int i = 0; i < n; ++i)
{
tmp += dp[i][j];
}
ans = min(ans, tmp);
}
return ans;
}
};