ABC400F Happy Birthday! 3
解题思路
初步观察
首先,必定存在一个位置,使得环从那里断成链之后,答案不变。
对于一条链,操作两两之间,如果不是不相交,就是包含关系,不然必定不优。
具体做法
题目给出的 \(b+X_c\) 这个式子中,既有与区间长度 \(b\),又有和具体颜色有关的 \(X_c\)。
直接贪心我们难以平衡这两者。
此时,再根据初步观察的“操作之间不相交/包含”的性质我们容易对链的情况设计出一个区间 \(\text{DP}\),
记 \(f_{l,r}\) 为:把区间 \([l,r]\) 染成最终颜色的方案数。
有下列几种转移:
- \(l\) 点单独染色
- 选择一个 \([l+1,r]\) 中和 \(l\) 同色位置 \(k\),并且把 \(l\) 点和 \(k\) 点一起染色,多出来的贡献是 \([l,k-1]\) 这一段。
这是链的情况。原题目中环的情况可以考虑将数组复制一遍拼接到尾部,然后对所有长为 \(n\) 的区间取个 \(\min\) 就是答案。
代码实现
点击查看代码
#include <bits/stdc++.h>
#define FL(i, a, b) for (int i = (a); i <= (b); ++i)
#define FR(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
typedef long long ll;
constexpr int N = 810;
constexpr ll INF = 1e14;
int n, c[N], x[N];
ll f[N][N];
int main() {
scanf("%d", &n);
FL(i, 1, n) {
scanf("%d", &c[i]);
c[n + i] = c[i];
}
FL(i, 1, n) {
scanf("%d", &x[i]);
}
FL(len, 1, n) {
FL(l, 1, n * 2 - len + 1) {
int r = l + len - 1;
f[l][r] = x[c[l]] + 1 + f[l + 1][r];
FL(k, l + 1, r) {
if (c[l] == c[k]) {
f[l][r] = min(f[l][r], f[l + 1][k - 1] + f[k][r] + (k - l));
}
}
}
}
ll ans = INF;
FL(i, 1, n) {
ans = min(ans, f[i][i + n - 1]);
}
printf("%lld\n", ans);
return 0;
}

浙公网安备 33010602011771号