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。(具体方程看代码)
坑点就是初始化,还有注意找最小值。
1 #include<iostream> 2 #include<cstdio> 3 #include <cctype> 4 #include<algorithm> 5 #include<cstring> 6 #include<cmath> 7 #include<string> 8 #include<cmath> 9 #include<set> 10 #include<vector> 11 #include<stack> 12 #include<queue> 13 #include<map> 14 using namespace std; 15 #define ll long long 16 #define mem(a,x) memset(a,x,sizeof(a)) 17 #define se second 18 #define fi first 19 const int INF= 0x3f3f3f3f; 20 const int N=1e6+5; 21 22 ll n,m,k,a[105],p[105][105],dp[105][105][105]; 23 24 int main() 25 { 26 cin>>n>>m>>k; 27 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 28 for(int i=1;i<=n;i++) 29 for(int j=1;j<=m;j++) scanf("%d",&p[i][j]); 30 31 for(int i=1;i<=n;i++) 32 for(int u=1;u<=m;u++) 33 for(int v=1;v<=k;v++) dp[i][u][v]=1e18; 34 35 if(a[1]==0){ //初始化 如果第一个点没被涂色 36 for(int i=1;i<=m;i++) 37 dp[1][i][1]=p[1][i]; //涂上第一个点对应的p[1][j] ,此时v=1 38 } 39 else{ //第一个点被涂色了 40 dp[1][a[1]][1]=0; //=0 ,因为这样的点 不计入结果 41 } 42 43 for(int i=2;i<=n;i++) 44 { 45 if(a[i]==0) 46 { 47 for(int u=1;u<=m;u++) 48 { 49 for(int v=1;v<=k;v++) 50 { 51 //下面比较v不变的时候: 52 dp[i][u][v]=min(dp[i][u][v], dp[i-1][u][v]+p[i][u] ); 53 54 //下面比较v 变的时候: 55 for(int j=1;j<=m;j++) 56 { 57 if(j!=u && v>1) 58 dp[i][u][v]=min(dp[i][u][v],dp[i-1][j][v-1]+p[i][u] ); 59 } 60 //通过以上 找出:对相同的i,在u在[1,m]和v在[1,k]范围内dp[i][u][v]的最小值 61 } 62 } 63 } 64 else{ 65 for(int u=1;u<=m;u++) 66 { 67 for(int v=1;v<=k;v++) 68 { 69 dp[i][a[i]][v]=min(dp[i][a[i]][v],dp[i-1][a[i]][v]); 70 for(int j=1;j<=m;j++) 71 { 72 if(j!=a[i] && v>1) 73 dp[i][a[i]][v]=min(dp[i][a[i]][v],dp[i-1][j][v-1]); 74 } 75 } 76 } 77 } 78 } 79 ll ans=1e18; 80 for(int i=1;i<=m;i++) 81 ans=min(ans,dp[n][i][k]); 82 if(ans==1e18) cout<<-1; 83 else cout<<ans<<endl; 84 }