Codeforces #369 (Div. 2) C. Coloring Trees (3维dp

http://codeforces.com/group/1EzrFFyOc0/contest/711/problem/C

https://blog.csdn.net/qq_36368339/article/details/78568585?locationNum=6&fps=1  题解

题意:(真难理解)有n个点,m种颜色,你要给n个点上没有颜色的点染色。每个点i对应染的颜色j有一个颜料消耗,p[i][j]是点i染成j颜色的花费,你必须保证有k段颜色的点,输出最少花费多少颜料。

思路:题意稍微不太好理解。。。 
dp[i][j][v]:位置i染第j种颜料恰好有v段颜色,所花费的颜料数量; 
第i个位置没被染色:i已经确定,但j,v未知,需要暴力枚举。 
第i个位置已被染色:i,j已经确定,只需要暴力枚举v。(具体方程看代码) 
坑点就是初始化,还有注意找最小值。

 #include<iostream>
#include<cstdio>
#include <cctype>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#include<queue>
#include<map>
using namespace std;
#define ll long long
#define mem(a,x) memset(a,x,sizeof(a))
#define se second
#define fi first
const int INF= 0x3f3f3f3f;
const int N=1e6+; ll n,m,k,a[],p[][],dp[][][]; int main()
{
cin>>n>>m>>k;
for(int i=;i<=n;i++) scanf("%d",&a[i]);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) scanf("%d",&p[i][j]); for(int i=;i<=n;i++)
for(int u=;u<=m;u++)
for(int v=;v<=k;v++) dp[i][u][v]=1e18; if(a[]==){ //初始化 如果第一个点没被涂色
for(int i=;i<=m;i++)
dp[][i][]=p[][i]; //涂上第一个点对应的p[1][j] ,此时v=1
}
else{ //第一个点被涂色了
dp[][a[]][]=; //=0 ,因为这样的点 不计入结果
} for(int i=;i<=n;i++)
{
if(a[i]==)
{
for(int u=;u<=m;u++)
{
for(int v=;v<=k;v++)
{
//下面比较v不变的时候:
dp[i][u][v]=min(dp[i][u][v], dp[i-][u][v]+p[i][u] ); //下面比较v 变的时候:
for(int j=;j<=m;j++)
{
if(j!=u && v>)
dp[i][u][v]=min(dp[i][u][v],dp[i-][j][v-]+p[i][u] );
}
//通过以上 找出:对相同的i,在u在[1,m]和v在[1,k]范围内dp[i][u][v]的最小值
}
}
}
else{
for(int u=;u<=m;u++)
{
for(int v=;v<=k;v++)
{
dp[i][a[i]][v]=min(dp[i][a[i]][v],dp[i-][a[i]][v]);
for(int j=;j<=m;j++)
{
if(j!=a[i] && v>)
dp[i][a[i]][v]=min(dp[i][a[i]][v],dp[i-][j][v-]);
}
}
}
}
}
ll ans=1e18;
for(int i=;i<=m;i++)
ans=min(ans,dp[n][i][k]);
if(ans==1e18) cout<<-;
else cout<<ans<<endl;
}
上一篇:Codeforces Round #369 (Div. 2)-C Coloring Trees


下一篇:Android中的动画