题目链接
题意:给你一列树,有n颗。给你m种颜色,这一列树中有些已经被涂好颜色了,但有些没有涂颜色。现在要给这些没有涂颜色的树上色,对于第i颗树,要涂第j种颜色,需要消耗p[i][j]的颜料。定义这一列树的美丽值为连续相同颜色段的段数。问使得美丽值为k的所需消耗的颜料的最小值。
思路:dp[i][j][k]代表前i棵树分成k组,第i棵为j色的最小价值,考虑一下这个dp的转移,其实就与前一棵树的颜色一不一样就行转移。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=105;
const ll inf=1e18;
ll dp[maxn][maxn][maxn];//dp[i][j][k]代表前i棵树分成k组,第i棵为j色的最小价值
ll cost[maxn][maxn],a[maxn];
int main()
{
int n,m,k;
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) scanf("%lld",&cost[i][j]);
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) for(int x=1;x<=k;++x) dp[i][j][x]=inf;
if(a[1]==0) for(int i=1;i<=m;++i) dp[1][i][1]=cost[1][i];
else dp[1][a[1]][1]=0;
for(int i=2;i<=n;++i)
{
if(a[i]!=0)
{
for(int j=1;j<=m;++j)
for(int x=1;x<=k;++x)
if(a[i]==j) dp[i][a[i]][x]=min(dp[i][a[i]][x],dp[i-1][j][x]);
else dp[i][a[i]][x+1]=min(dp[i][a[i]][x+1],dp[i-1][j][x]);
}
else {
for(int j=1;j<=m;++j)//j为当前i的颜色
for(int x=1;x<=m;++x)//x为i-1的颜色
for(int y=1;y<=k;++y)
if(j==x) dp[i][j][y]=min(dp[i][j][y],dp[i-1][j][y]+cost[i][j]);
else dp[i][j][y+1]=min(dp[i][j][y+1],dp[i-1][x][y]+cost[i][j]);
}
}
ll ans=inf;
for(int i=1;i<=m;++i)
ans=min(ans,dp[n][i][k]);
printf("%lld\n",ans==inf?-1:ans);
}