Codeforces Round #369 (Div. 2) C. Coloring Trees(三维DP)

题目链接
在这里插入图片描述
在这里插入图片描述
题意:给你一列树,有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);
 } 
发布了328 篇原创文章 · 获赞 1 · 访问量 9097

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/105229375