题目链接: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;
}

 

posted on 2016-08-30 14:10  小小八  阅读(186)  评论(0编辑  收藏  举报