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];//返回这个容量下的最大利润
            }
        }
    }
  • 相关阅读:
    HDU 4870 Rating(高斯消元 )
    iOS开发者账号详细介绍
    iOS之Block
    CocoaPods 安装和使用
    搭建自己的局域网服务器
    MarkDown语法收集
    正则表达式参考表
    iOS企业级应用打包与部署
    iOS开发之代码加载方式进入APP的界面
    shell脚本小Demo
  • 原文地址:https://www.cnblogs.com/zhangyang4674/p/11282193.html
Copyright © 2011-2022 走看看