Codeforces Round #369 (Div. 2) C. Coloring Trees 动态规划

来源:互联网 发布:域名到期查询 编辑:程序博客网 时间:2024/05/21 01:28

题目链接:这里
题意:给你n棵树,如果ci为0的话,那么这棵树就没有上色,否则这棵树就是ci颜色的。
相同颜色的树会被当成一段,现在你要恰好刷漆刷成k段,问你最小花费是多少。
把第i棵树刷漆刷成j颜色的花费为p[i][j]。
解法: dp[i][j][k]表示第i棵树,刷成了j颜色,当前有k段的最小花费是多少。直接暴力n^4的转移,稍加优化可以变成n^3的,这里显然还可以前缀和优化。

//CF 711C#include <bits/stdc++.h>using namespace std;const int maxn = 105;const long long inf = 1e15;long long dp[2][maxn][maxn];//第i颗树,刷成了j颜色,当前有k段的最小花费int n, m, K, c[maxn], p[maxn];int now = 0, pre = 1;long long ans = inf;int main(){    cin >> n >> m >> K;    for(int i = 1; i <= n; i++) cin >> c[i];    for(int j = 0; j <= m; j++){        for(int k = 0; k <= n; k++){            dp[now][j][k] = inf;        }    }    for(int i = 1; i <= m; i++) scanf("%d", &p[i]);    if(c[1] == 0){        for(int j = 1; j <= m; j++){            dp[now][j][1] = p[j];        }    }    else{        dp[now][c[1]][1] = 0;    }    for(int i = 2; i <= n; i++){        swap(pre, now);        for(int j = 0; j <= m; j++){            for(int k = 0; k <= n; k++){                dp[now][j][k] = inf;            }        }        for(int j = 1; j <= m; j++) cin >> p[j];        if(c[i] == 0){            for(int j = 1; j <= m; j++){                for(int k = 1; k <= n; k++){                    dp[now][j][k] = min(dp[now][j][k], dp[pre][j][k] + p[j]);                    for(int t = 1; t <= m; t++){                        if(t == j) continue;                        dp[now][j][k] = min(dp[now][j][k], dp[pre][t][k-1] + p[j]);                    }                }            }        }        else{            for(int k = 1; k <= n; k++){                dp[now][c[i]][k] = min(dp[now][c[i]][k], dp[pre][c[i]][k]);                for(int t = 1; t <= m; t++){                    if(t == c[i]) continue;                    dp[now][c[i]][k] = min(dp[now][c[i]][k], dp[pre][t][k-1]);                }            }        }    }    for(int i = 1; i <= m; i++){        ans = min(ans, dp[now][i][K]);    }    if(ans == inf) puts("-1");    else printf("%lld\n", ans);}
0 0
原创粉丝点击