题目
分析
枚举位移的次数
k
k
k,显然
0
≤
k
<
N
0 \leq k < N
0≤k<N,接下来只需要知道每个史莱姆在什么时候被取走,因此答案为
min
0
≤
k
<
N
{
k
x
+
∑
1
≤
i
≤
N
min
{
a
i
,
a
i
+
1
,
⋯
,
a
i
+
k
}
}
\min_{0 \leq k < N} \left\{kx + \sum_{1 \leq i \leq N} \min\{a_i, a_{i + 1}, \cdots, a_{i + k}\}\right\}
0≤k<Nmin{kx+1≤i≤N∑min{ai,ai+1,⋯,ai+k}} 注意下标加
k
k
k 需要循环移位。
但这是
O
(
N
3
)
O(N^3)
O(N3) 的。考虑
min
{
a
i
,
a
i
+
1
,
⋯
,
a
i
+
k
}
\min\{a_i, a_{i + 1}, \cdots, a_{i + k}\}
min{ai,ai+1,⋯,ai+k} 的部分,实际上可以 DP 动态更新。即枚举到当前
k
,
i
k, i
k,i 的时候用
a
i
+
k
a_{i + k}
ai+k 更新之前维护的值即可。
代码
#include <algorithm>
#include <cstdio>
#include <cstring>
typedef long long LL;
const int MAXN = 2000;
const LL INF = 0x3f3f3f3f;
int N, X;
int A[MAXN + 5];
int Dp[MAXN + 5];
int main() {
scanf("%d%d", &N, &X);
LL Ans = 1ll << 60;
for (int i = 1; i <= N; i++)
scanf("%d", &A[i]), Dp[i] = INF;
for (int k = 0; k < N; k++) {
LL cur = 0;
for (int i = 1; i <= N; i++)
cur += Dp[i] = std::min(Dp[i], A[(i + k - 1) % N + 1]);
Ans = std::min(Ans, (LL)k * X + cur);
}
printf("%lld", Ans);
return 0;
}