题目链接:C. Coloring Trees
题意:给出n棵树的颜色,有些树被染了,有些没有。现在让你把没被染色的树染色。使得beauty = k。问,最少使用的颜料是多少。
K:连续的颜色为一组,一共有多少组。
颜料用量:p[i][j]表示第i棵树用颜料j染色 需要p[i][j]颜料。
思路:DP.
dp方程:dp[i][j][k] = a 表示前i棵树beauty = j,且第j棵树染色为k时,需要的最少颜料为a。
状态转移:初始化第一棵树dp[1][1][col[1]or(1~m)].
遍历剩下的2~n棵树i,beauty = j (1~min(k, i))时,如果已经被染色了,直接更新dp[i][j or (j+1)][col[i]]为min(dp[i-1][j][1~m])。
如果没被染色,尝试染第kkk(1~m)种颜色,并更新dp[i][j or (j+1)][kkk]为min(dp[i-1][j][kk]) (1<=kk<=m, 1<=KKK<=m)。
喜欢这个题。
#include <stdio.h> #include <string.h> #include <iostream> #define maxn 210 #define inf 1e16 #define LL long long using namespace std; int col[maxn]; int p[maxn][maxn]; LL dp[maxn][maxn][maxn]; int main() { int n, m, k; // freopen("in.cpp", "r", stdin); while(~scanf("%d%d%d", &n, &m, &k)) { //input for (int i=1; i<=n; ++i) { scanf("%d", &col[i]); } for (int i=1; i<=n; ++i) { for (int j=1; j<=m; ++j) { scanf("%I64d", &p[i][j]); } } //init for (int i=1; i<=n; ++i) { for (int j=1; j<=k; ++j) { for (int kk=1; kk<=m; ++kk) { dp[i][j][kk] = inf; } } } if (col[1]) dp[1][1][col[1]] = 0; else { for (int i=1; i<=m; ++i) { dp[1][1][i] = p[1][i]; } } //solve for (int i=2; i<=n; ++i) { ///第i棵树 for (int j=1; j<=i && j<=k; ++j) { /// i-1 beauty=j if (col[i]) { ///第i棵树颜色已经有了 for (int kk=1; kk<=m; ++kk) { /// if (kk == col[i]) dp[i][j][col[i]] = min(dp[i][j][col[i]], dp[i-1][j][kk]); else dp[i][j+1][col[i]] = min(dp[i][j+1][col[i]], dp[i-1][j][kk]); } } else { for (int kk=1; kk<=m; ++kk) { ///i for (int kkk=1; kkk<=m; ++kkk) { ///i-1 if (kk == kkk) dp[i][j][kk] = min(dp[i][j][kk], dp[i-1][j][kkk]+p[i][kk]); else dp[i][j+1][kk] = min(dp[i][j+1][kk], dp[i-1][j][kkk]+p[i][kk]); } } } } } LL ans = inf; for (int i=1; i<=m; ++i) { ans = min(ans, dp[n][k][i]); } if (ans == inf) ans = -1; printf("%I64d\n", ans); } return 0; }