zoukankan      html  css  js  c++  java
  • 动态规划之01背包问题和三角形问题

    01背包问题

    有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
    这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。
    状态:用f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值,其状态转移方程为f[i][v]=max{ f[i-1][v],  f[i-1][v-c[i]]+w[i] }。
    复杂度分析:
    状态数:O(NV), 迁移:O(1)
    总复杂度:O(NV)
     
    状态f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。
    对于“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。
    如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];
    如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。
    n状态转移方程:

      f[i][v]=max{ f[i-1][v],  f[i-1][v-c[i]]+w[i] }

    时间复杂度O(NV)
    由于计算f[i][v]时只用到f[i-1][v]和f[i-1][v-c[i]],在每次主循环中我们以v=V..0的顺序推f[v],这样就保证推f[v]时f[v-c[i]]保存的是状态f[i-1][v-c[i]]的值,f[v]保存的是状态f[i-1][v]的值。
    n伪代码如下:

      for i=1..N

          for v=V..cost

             f[v]=max{f[v], f[v-c[i]] + w[i]};

    空间复杂度成功降到O(V)
           // 01背包问题
            public static void Pack(int[] cost, int[] weight, int v)
            {
                int[] volumn = new int[v + 1];
                volumn[0] = 0; //空间复杂度成功降到O(V),如果用二维数组则为o(NV)
    
    
                for (int i = 1; i < v + 1; i++)
                {
                   // 1). 如果背包并非必须被装满,那么任何容量的背包都有一个合法解“什么都不装”,
                    // 这个解的价值为0,所以初始时状态的值也就全部为0了
                    // volumn[i] = 0;
    
                    //2). 如果要求背包恰好装满,
                    // 那么此时只有容量为0的背包可能被价值为0的nothing“恰好装满”,其它容量的背包均没有合法的解,
                    // 属于未定义的状态,它们的值就都应该是-∞了。
                    volumn[i] = int.MinValue; 
                  
                }
    
                for (int j = 0; j < cost.Length; j++)
                {
                    for (int t = v; t >= cost[j]; t--)
                    {
                      
                        if (t >= cost[j]) // 容量要大于物体容积,才可能把物体放进去。
                        {
                            volumn[t] = Math.Max(volumn[t], volumn[t - cost[j]] + weight[j]);
                              // f[i][v] = Max{f[i-1][[v], f[i-1][v-c[i]] +w[i]}
                        }                    
                    }
                }
            }
     数字三角形问题 
    给定一个具有N层的数字三角形,从顶至底有多条路径,每一步可沿左斜线向下或沿右斜线向下,路径所经过的数字之和为路径得分,请求出最小路径得分

               2

           6   2

         1   8   4

       1   5   6   8 

         数字三角形

    // 利用01背包问题的思路解决数字三角形问题.
            public static void ShortPath(int n)
            {
                //       2
                //    6   2
                //  1   8   4
                //1   5   6   8
    
                //  数字三角形 
    
                int[][] array = new int[4][];
    
                array[0] = new int[] { 2 };
                array[1] = new int[] { 6, 2 };
                array[2] = new int[] { 1, 8, 4 };
                array[3] = new int[] { 1, 5, 6, 8 };
    
                int[] value = new int[n];
    
                for (int k = 0; k < n; k++)
                {
                    value[k] = array[n - 1][k];
                }
    
               // 递推关系式:f(i)(j) = min{f(i+1)(j), f(i+1)(j+1)} + array[i][j]
    
                for (int i = n - 2; i >= 0; i--)
                {
                    for (int j = 0; j <= i; j++)
                    {
                        value[j] = Math.Min(value[j], value[j + 1]) + array[i][j];
    
                        //递推关系式:f(i)(j) = min{f(i+1)(j), f(i+1)(j+1)} + array[i][j]
                        // 左下角,(x+1,y),右下角的线(X+1, y+1)
                    }
                }
            }
  • 相关阅读:
    linux jdk1.8安装
    spring boot jar包 linux 部署
    mysql linux安装
    codesmith 三层架构
    数据库分库分表(sharding)系列(三) 关于使用框架还是自主开发以及sharding实现层面的考量
    android学习路线
    博客资源
    dotNET跨平台研究的相关文档
    Foundation框架—— 数组 (NSArray NSMutableArray )
    OC面向对象特性: 继承
  • 原文地址:https://www.cnblogs.com/Jessy/p/3488893.html
Copyright © 2011-2022 走看看