zoukankan      html  css  js  c++  java
  • 动态规划算法

    动态规划算法:

    切割钢条问题:不同长度的钢条的价格是不同的,怎样切割获取的利润最大。

    假设钢条的长度为n,怎样切割获取最大值

    普通方法实现:

      private static int  UpDown(int  n, int[] price)
            {
                if(n==0)//回调函数的终止条件
                {
                    return 0;
                }          
                int maxprice = 0;
                for (int i = 1; i <=n; i++)
                {
                    int Value = price[i] + UpDown(n-i,price);//利用了分治算法,分开求不同段的钢条的最大值,price[i]是切割的固定的长度,Up()是利用回调函数获取这个长度的利润最大值
                    if(maxprice<Value)
                    {
                        maxprice = Value;
                    }
                }
                return maxprice;
            }

    动态算法实现钢条切割的最大利润

    从顶到底实现:钢铁的切割

    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Incise
    {
        class Program
        {
            static void Main(string[] args)
            {
                int[] price = new int[] { 0,1,5,8,9,10,17,17,20,24,30};
                int[] StartValue = new int[11];//因为我们要经常求某个长度的钢条的最大值,所以我们可以用数组存储我们已近算出来的某个长度的最大利润。
              //  int n = int.Parse(Console.ReadLine());
                int MaxPrice= UpDown(9 ,price,StartValue);
                Console.WriteLine(MaxPrice);
                Console.ReadKey();
    
            }
            /// <summary>
            /// 根据不同长度的钢条价格获取最好的切割方案
            /// </summary>
            /// <param name="n"></param>
            /// <param name="price"></param>
            /// <returns></returns>
            private static int  UpDown(int  n, int[] price,int[] StartValue)
            {
                if(n==0)//回调函数的终止条件
                {
                    return 0;
                }   
                if(StartValue[n]!=0)//判断我们已经存储过这个值的最大利润时,可以直接使用最大利润
                {
                    return StartValue[n];
                }       
                int maxprice = 0;
                for (int i = 1; i <=n; i++)
                {
                    int Value = price[i] + UpDown(n-i,price,StartValue);//利用了分治算法,分开求不同段的钢条的最大值,price[i]是切割的固定的长度,Up()是利用回调函数获取这个长度的利润最大值
                    if(maxprice<Value)
                    {
                        maxprice = Value;
                    }
                }
                StartValue[n] = maxprice;//算出n的最大利润后,我们把值存储在数组中,以后在使用这个长度时,可以直接使用
                return maxprice;
            }
        }
    }

    从底到顶的钢条切割:会优化这个算法

     private static int ButtonUp(int n,int[] price,int [] StartValue)
            {
                if(n==0)//结束回调函数的条件
                {
                    return 0;
                }
                if(StartValue[n]!=0)//如果这个长度的钢条的最大利润已近计算出过,就直接把这个最大利润从数组中拿出来,直接使用
                {
                    return StartValue[n];
                }
                int MaxValue = 0;
                for (int i = 1; i <=n; i++)//N是钢条的长度,对这个钢条分解求最大利润
                {
                    int temp = 0;
                    for (int j = 1; j <=i; j++)
                    {
                        temp = price[j] + ButtonUp(i-j,price,StartValue);//从小到大的切割钢条,这样下一个钢条会直接使用上一个钢条的最大利润
                        if(temp>MaxValue)
                        {
                            MaxValue = temp;
                        }
                    }
                    StartValue[i] = MaxValue;
                }
                return StartValue[n];//StartValue数组中存储了,从0-n长度的钢条的最优解
            }

     动态规划解决背包问题

    背包问题可以使用穷举法和动态规划算法

    穷举法:计算出物品放入背包的各种可能,在判断每一种可能的重量是否超标,不超标的情况那个利润最大。核心思想是利用与运算得到每一种情况种的物品,用来计算利润

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace MaxBack
    {
        class Program
        {
            static void Main(string[] args)
            {          
                int Wht = 10;//背包的容量
                int[] price = new int[] {4,5,6 };//物品的价格
                int[] weight = new int[] { 3,4,5}; //物品的重量          
                Console.WriteLine(maxProfit(price, weight, Wht));//输出背包能放物品的最大利润
                Console.ReadKey();
            }
            /// <summary>
            /// 穷举法计算背包的最大利润
            /// </summary>
            /// <param name="price"></param>
            /// <param name="weight"></param>
            /// <param name="Wht"></param>
            /// <returns></returns>
            private static int maxProfit(int[] price, int[] weight, int Wht)
            {
                int MaxValue = 0;     //背包的最大利润    
                for (int i = 0; i < Math.Pow(2,weight.Length); i++)//背包放入物品的各种可能
                {         
                    int temp = 0, temp1 = 0;
                    for (int j = 0; j < weight.Length; j++)//用二进制的与运算计算出每一种可能的具体物品
                    {                
                       if ((Convert.ToInt32(Math.Pow(2, j)) & i)== Convert.ToInt32(Math.Pow(2, j)))//与运算为1的值表示这个物品要放入背包中
                        {                    
                            temp += price[j];//计算每一种情况要放入背包物品的总价格
                            temp1 += weight[j];//计算每一种情况要放入背包物品的总重量
                            if(temp1>Wht)//总量超过背包物品的总重量时,终止放入,计算下一种情况
                            {
                                break;
                            }
                        }
                    }
                    if(temp1<=Wht)//判断放入背包的重量小于背包重量的各种情况的最大利润
                    {
                        if(MaxValue<temp)
                        {
                            MaxValue = temp;
                        }
                    }
                }
                return MaxValue;//返回这个最大利润
            }
        }
    }

    动态规划算法:每一次只判断一个物品是放入和不放入的利润谁大,利用嵌套调用。

    使用动态规划算法,自上往下计算

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace BacKQuestion
    {
        class Program
        {
            /// <summary>
            /// 最大背包问题
            /// </summary>
            /// <param name="args"></param>
            static void Main(string[] args)
            {
                int wht = 5;
                int[] Weight = new int[] { 0,3,4,5};
                int[] price = new int[] { 0,4,5,6};
                int value = MaxValue(wht, Weight, price, price.Length-1);
                Console.WriteLine(value);
                Console.ReadKey();
            }
            /// <summary>
            /// 使用动态规划算法,选则物品放入背包,以获取最大利润
            /// </summary>
            /// <param name="wht"></param>
            /// <param name="Weight"></param>
            /// <param name="price"></param>
            /// <param name="index"></param>
            /// <returns></returns>
            private static int MaxValue(int wht,int[] Weight,int[] price,int index)
            {
                int Maxvalue1 = 0;
                int maxvalue2 = 0;
                if(index==0||wht==0)//当物品的个数为0时,或背包放不下时,结束放置物品
                {
                    return 0;
                }
                if(wht<Weight[index])//第I个物体放入背包时超重,选择放入第I-1个物体
                {
                    return MaxValue(wht, Weight, price, index - 1);//第i个物体放入时超重,选择放入第I-1个物体
                }
                else//第i个物体能放入背包中
                { 
                    Maxvalue1 = MaxValue(wht-Weight[index],Weight,price,index-1)+price[index];//第I个物体放入背包,在判断第i-1个物体要不要放入背包
                    maxvalue2 =MaxValue(wht, Weight, price, index-1);//第i个物体不放入背包,在判断第I-1个物体要不要放入背包
                    return Maxvalue1 > maxvalue2 ? Maxvalue1 : maxvalue2;//获取这两种情况的最大值返回
                }                                  
            }
        }
    }

    背包问题:动态规划算法自上而下优化方法。用二维数组Array[weight,]记录每一种重量的最大利润,

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace BacKQuestion
    {
        class Program
        {
            /// <summary>
            /// 最大背包问题
            /// </summary>
            /// <param name="args"></param>
            public static int[,] array = new int[11, 4];//int[i,j]i表示背包容量,j表示存储的物品数量,用数组存储不同容量下背包的最大利润
            static void Main(string[] args)
            {
                int wht = 10;
                int[] Weight = new int[] { 0,3,4,5};
                int[] price = new int[] { 0,4,5,6};
                int value = MaxValue(wht, Weight, price, price.Length-1);
                Console.WriteLine(value);
                Console.ReadKey();
            }
            /// <summary>
            /// 使用动态规划算法,选则物品放入背包,以获取最大利润
            /// </summary>
            /// <param name="wht"></param>
            /// <param name="Weight"></param>
            /// <param name="price"></param>
            /// <param name="index"></param>
            /// <returns></returns>
            private static int MaxValue(int wht,int[] Weight,int[] price,int index)
            {
                int Maxvalue1 = 0;
                int maxvalue2 = 0;
                if(index==0||wht==0)//当物品的个数为0时,或背包放不下时,结束放置物品
                {
                    return 0;
                }
                if(array[wht,index]!=0)
                {
                    return array[wht, index];
                }
                if(wht<Weight[index])//第I个物体放入背包时超重,选择放入第I-1个物体
                {
                    array[wht,index-1]= MaxValue(wht, Weight, price, index - 1);//第i个物体放入时超重,选择放入第I-1个物体
                    return array[wht,index-1];
                }
                else//第i个物体能放入背包中
                { 
                    Maxvalue1 = MaxValue(wht-Weight[index],Weight,price,index-1)+price[index];//第I个物体放入背包,在判断第i-1个物体要不要放入背包
                    maxvalue2 =MaxValue(wht, Weight, price, index-1);//第i个物体不放入背包,在判断第I-1个物体要不要放入背包
                  
                    if(Maxvalue1>maxvalue2)
                    {
                        array[wht, index] = Maxvalue1;//记录当存储的空间为wht,放入物品与不放入物品时,把利润最大的值记录下来
                    }
                    else
                    {
                        array[wht, index] = maxvalue2;
                    }
                }
                return array[wht,index];                                
            }
        }
    }

    背包问题:使用动态算法自下而上记录每一种情况的最大利润

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ButtonToUp
    {
        class Program
        {
            public static int[,] array = new int[13, 4];//int[i,j]i表示背包容量,j表示存储的物品数量,用数组存储不同容量下背包的最大利润
            static void Main(string[] args)
            {
                int wht = 12;
                int[] Weight = new int[] { 0, 3, 4, 5 };
                int[] price = new int[] { 0, 4, 5, 6 };
                int value = MaxValue(wht, Weight, price, price.Length - 1);
                Console.WriteLine(value);
                Console.ReadKey();
             
            }
    
            private static int MaxValue(int wht, int[] weight, int[] price, int v)
            {
                if(array[wht,v]!=0)//多次查找背包的最大利润时,如果这个值已近被记录下来,可以直接使用数组中存储的值
                {
                    return array[wht, v];
                }
                for (int i = 1; i <=wht; i++)
                {
                   
                    for (int j = 1; j <=v; j++)
                    {
                        if (array[i,j] != 0)//要查找的这个值虽然没存储在数组中,但他前面的可能性已近存储了,所以可以直接使用
                        {
                            return array[i,j];
                        }
                        if (i < weight[j])//如果这个物体的重量大于背包的重量,则这种情况不放入这个物体
                        {
                            array[i, j] = array[i, j - 1];
                        }
                        else//如果这个物体的重量小于背包的重量,物体可以放入也可以不放,判断那种情况的利润最大,把他记录下来
                        {
                            int Maxprice1 = price[j] + array[i-weight[j], j - 1];
                            int Maxprice2 = array[i, j - 1];
                            if (Maxprice1 > Maxprice2)
                            {
                                array[i, j] = Maxprice1;
                            }
                            else
                            {
                                array[i, j] = Maxprice2;
                            }
                        }
                    }
                }
                return array[wht, v];//返回这个容量下的最大利润
            }
        }
    }
  • 相关阅读:
    2. Add Two Numbers
    1. Two Sum
    leetcode 213. 打家劫舍 II JAVA
    leetcode 48. 旋转图像 java
    leetcode 45. 跳跃游戏 II JAVA
    leetcode 42. 接雨水 JAVA
    40. 组合总和 II leetcode JAVA
    24. 两两交换链表中的节点 leetcode
    1002. 查找常用字符 leecode
    leetcode 23. 合并K个排序链表 JAVA
  • 原文地址:https://www.cnblogs.com/zhangyang4674/p/11282193.html
Copyright © 2011-2022 走看看