• CodeForces


    1.求达到某个状态的最小值,考虑用动态规划方式求解。

    2.考虑第i棵树的决策,他的颜色对答案及状态的贡献受两个因素的影响:

    ①上一颗树颜色的选取

    ②考虑前i-1棵树已经分成了几段

    定义dp[i][j][k] : 第i棵树 当涂j颜色 分成k段时的最小消耗是多少

    如果已经涂上色了 dp[i][j][k] = min(dp[i-1][j][k], dp[i-1][w!=j][k-1])

    如果没有涂上色 dp[i][j][k] = min(dp[i-1][j][k], dp[i-1][w!=j][k-1] + cost[i][j]  ---->实现比较考代码能力

    注意初始化 

    dp把i= 1作为开始点 i=0作为原始点 给i=0初始化 让它的状态 传递到下一个状态

    dp[0][0][0] = 0----->因为不存在0树 所以成本为0

    其余memset(dp, INF, sizeof(dp))

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string>
     4 #include <string.h>
     5 #include <map>
     6 #include <fstream>
     7 #include <set>
     8 #define MAXC 107
     9 #define INF 1e15+7 //最开始0x6f6f6f6f 在test12挂了 说明肯定是大数爆了  INF 设小了
    10 #define READ() freopen("in.txt", "r", stdin);
    11 using namespace std;
    12 typedef long long ll;
    13 int n, m, k;
    14 int color[MAXC];
    15 ll cost[MAXC][MAXC];
    16 ll dp[MAXC][MAXC][MAXC];
    17 
    18 ll solve()
    19 {
    20     for (int i = 0; i <= n; i++)
    21     {
    22         for (int j = 0; j <= m; j++)
    23         {
    24             for (int l = 0  ; l <= k; l++)
    25             {
    26                 dp[i][j][l] = INF;
    27             }
    28         }
    29     }
    30     dp[0][0][0] = 0;
    31     for (int i = 1; i <= n; i++)
    32     {
    33         if (color[i] != 0)
    34         {
    35             for (int l = 1; l<= k; l++)
    36             {
    37                 dp[i][color[i]][l] = min(dp[i][color[i]][l], dp[i-1][color[i]][l]);//和i-1同一个色
    38                 ll minn = INF;
    39                 for (int z = 0; z <= m; z++)//--->>要从dp[0][0][0] 状态转出来
    40                 {
    41                     if (z != color[i]) minn = min(minn, dp[i-1][z][l-1]);//跟前i-1种不同色 前i-1种有l-1组
    42                 }
    43                 dp[i][color[i]][l] = min(dp[i][color[i]][l], minn);
    44             }
    45 
    46         }
    47         else
    48         {
    49             for (int l = 1; l <= k; l++)
    50             {
    51                 for (int j = 1; j <= m; j++)
    52                 {
    53                     dp[i][j][l] = min(dp[i][j][l], dp[i-1][j][l]) + cost[i][j];//涂一样
    54                     ll minn = INF;
    55                     for (int z = 0; z <= m; z++)
    56                     {
    57                         if (z != j) minn = min(minn, dp[i-1][z][l-1]);
    58                     }
    59                     dp[i][j][l] = min(dp[i][j][l], minn + cost[i][j]);
    60                 }
    61             }
    62         }
    63     }
    64     ll res = INF;
    65     for (int j = 1; j <=m; j++)
    66     {
    67         res = min(res, dp[n][j][k]);
    68     }
    69     return res;
    70 }
    71 
    72 
    73 int main()
    74 {
    75     READ()
    76     scanf("%d%d%d",&n, &m, &k);
    77     for (int i = 1; i <= n; i++)
    78     {
    79         int c;
    80         scanf("%d", &c);
    81         color[i] = c;
    82     }
    83     for (int i = 1; i <= n; i++)
    84     {
    85         for (int j = 1; j <= m; j++)
    86         {
    87             scanf("%lld", &cost[i][j]);
    88         }
    89     }
    90     ll ans = solve();
    91     if (ans == INF) cout << -1 << endl;
    92     else cout << ans << endl;
    93 }

    对dp的一点小总结 

    dp的特征 数据不是很大 求解最优值 并要在每一步做出决策

    如果纯搜 复杂度m^n次 

    但是dp得好处在于有信息的传递  ---> 对信息的压缩

    考虑的这一点就比较容易得出思路 确定有几个维度

    j-1 告诉 j 颜色用什么 -->显然需要一个颜色维度

    k-1 告诉 k已经分成了多少段 --> 显然需要对段数记录的维度

    当然第几棵树做什么决策 也需要对第几棵树记录 可以用之前的数组 的重复利用节省内存

    也可以添加 i维度 记录第几棵树 

  • 相关阅读:
    HTTP状态码
    Hibernate的配置与简单使用
    Java基础学习总结 -- 多线程的实现
    MySQL学习笔记 -- 数据表的基本操作
    Java基础学习 -- I/O系统、流
    理解文件的编码
    Java基础学习 -- 异常
    Java基础学习 -- GUI之 事件处理基础
    Java基础学习总结 -- 图形用户界面GUI
    Java基础学习 -- 接口
  • 原文地址:https://www.cnblogs.com/oscar-cnblogs/p/6435536.html
Copyright © 2020-2023  润新知