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);
 } 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值