1. 程式人生 > 其它 >cf711 C. Coloring Trees(dp)

cf711 C. Coloring Trees(dp)

思路:

f(i,j,p)表示第1~i棵樹已染色, 染成了j組,第i棵樹染成p顏色的最小花費。複雜度 \(O(nkm^2)\)。其實還可以維護2個最值優化到 \(O(nkm)\)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 105;
int n, m, k, col[N], cost[N][N];
ll f[N][N][N];
signed main()
{
    cin >> n >> m >> k;
    for(int i = 1; i <= n; i++) cin >> col[i];
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            cin >> cost[i][j];

    memset(f, 0x3f, sizeof f);
    if(col[1]) f[1][1][col[1]] = 0;
    else for(int i = 1; i <= m; i++) f[1][1][i] = cost[1][i];

    for(int i = 2; i <= n; i++)
    for(int j = 1; j <= k; j++)
        for(int p = 1; p <= m; p++) //i的顏色
        {
            if(col[i] && col[i] != p) continue;
            for(int q = 1; q <= m; q++) //i-1的顏色
            {
                if(col[i-1] && col[i-1] != q) continue;

                if(p == q) //i和i-1同色
                {
                    if(!col[i]) //i無色
                        f[i][j][p] = min(f[i][j][p], f[i-1][j][q] + cost[i][p]);
                    else if(col[i] == q) //i有色
                        f[i][j][p] = min(f[i][j][p], f[i-1][j][q]);
                }
                else //i和i-1異色
                {
                    if(!col[i]) //i無色
                        f[i][j][p] = min(f[i][j][p], f[i-1][j-1][q] + cost[i][p]);
                    else if(col[i] != q) //i有色
                        f[i][j][p] = min(f[i][j][p], f[i-1][j-1][q]);
                }
            }
        }

    ll ans = 1e18;
    for(int i = 1; i <= m; i++) ans = min(ans, f[n][k][i]);
    cout << (ans < 1e18 ? ans : -1);

    return 0;
}