题解:P10715 【MX-X1-T3】「KDOI-05」简单的序列问题
cancan123456 · · 题解
首先将
因此考虑将一次交换看成两次切换:
容易发现如果
现在设计 DP 状态:
初始状态显然为
考虑从
求答案时,需要保证
时间复杂度为
#include <cstdio>
using namespace std;
const int N = 505;
int a[N], c[N], f[N][N][N];
int min(int a, int b) {
return a < b ? a : b;
}
int main() {
int T;
scanf("%d", &T);
for (int n; T != 0; T--) {
scanf("%d", &n);
int cnt = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
a[i] %= 2;
cnt += a[i];
}
for (int i = 1; i <= n; i++) {
scanf("%d", &c[i]);
}
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n; j++) {
for (int k = 0; k <= n; k++) {
f[i][j][k] = 0x3f3f3f3f;
}
}
}
// f[i][j][k] 为前 i 个数中 a[x] = 1 有 j 个,b 中 1 的个数为 k 的最小代价.
f[0][0][0] = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j <= n; j++) {
for (int k = 0; k <= n; k++) {
if (f[i][j][k] != 0x3f3f3f3f) {
for (int l = 0; l <= 1; l++) {
int & to = f[i + 1][j + l][k + (j + l) % 2];
to = min(to, f[i][j][k] + c[i + 1] * (a[i + 1] ^ l));
}
}
}
}
}
for (int i = 0; i <= n; i++) {
if (f[n][cnt][i] != 0x3f3f3f3f) {
printf("%d ", f[n][cnt][i]);
} else {
printf("-1 ");
}
}
printf("\n");
}
return 0;
}