zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    若不曾忘记,便不必追忆
    C# 随机生成中文字符串
    C# SQLiteHelper
    C# SQLHelper
    C# Microsoft SQL Server 操作
    C# Excel 操作
    C# XML文件操作(续)
    C# 遍历XML文件,添加,更新,删除节点
    MES系统简介
    SQL Server 存储过程(转)
  • 原文地址:https://www.cnblogs.com/thunder-110/p/9408321.html
Copyright © 2011-2022 走看看