思路:
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;
}