zoukankan      html  css  js  c++  java
  • 简单理解算法篇--动态规划

        动态规划方法通常用来求解最优化问题,这些问题有很多种解,但我们希望寻求最优解。

       满足两个条件既可以使用动态规划

       1.具有最优子结构

       2.子问题重叠

     至于这两点是什么意思?先看个问题

    现在有个钢筋长度和价格对应的表,问:给你个长度为n的钢筋怎么卖最划算?

    长度 1 2 3 4  5   6  7   8   9  10
    价格 1 5 8 9 10 17 17 20 24 30

    现在就是要把所有的切法都遍历一遍,找出最划算的切法,当你把钢筋切了一刀后,是不是变成了两段?那就要考虑的就是这两段怎么切最划算,这样会比较复杂,不妨我们这样:

    把钢筋切一刀,成两半,但左边那一半不在考虑,直接按价格卖出,只考虑右边那一半,这样是不是比较简单?当然为了遍历所有切法,左边那部分是从1到n递增的。然而现在我们现在的问题就是变成切一条钢筋,左边不动,把右边又看成一条独立的钢筋切,左边不动,把右边....是不是有递归的味道了?像这样一直重复的解决同一种问题(把右边的钢筋独立看成独立的一条钢筋,继续切)就叫做子问题重叠。

    至于什么是最优子结构?顾名思义就是子问题的最优解就是问题的最优解。什么意思?就是如果把钢筋分成A和B两段,那么A的最优解和B的最优解合起来就是原问题的最优解..

    有人说这不是废话么?来看一个例子

    现在有一个正方形,顶点为a,b,c,d,要求a->c的最短路径,是不是可以分成a->b和b->c两个子问题?a->b的最短路径当然是a->b啦,那么合起来路径就是a->b->c,这个符合最优子结构。

    但是要求a->b的最长路径呢?假如按照子问题方法求解的话我们又会分成a->c和c->b两个子问题,a->c的最长路径为a->d->c,同理c->b的最长路径为c->d->a->b ,那么最长路径是不是a->b?显然不是,所以这个就不满足最优子结构。

    下面是实现的代码

            static void Main(string[] args)
            {
                int[] p = new int[]{0,1,5,8,9,10,17,17,20,24,30};    
                int n=Convert.ToInt32(Console.ReadLine());
                DateTime starDt = DateTime.Now;
                int maxp=CUTROD(p,n);
                DateTime endDt = DateTime.Now;
                TimeSpan st = endDt - starDt;
                Console.WriteLine(maxp);//最优值
                Console.WriteLine(st);//消耗时间
            }
            public static int CUTROD(int[] p, int n)
            {
                int q = -1;
                if (n == 0)
                {
                    return 0;
                   
                }
                else
                {
                    for (int i = 1; i <= n; i++)
                    {
                        q = max(q, p[i]+CUTROD(p, n - i));
                    }
                    return q;
                }   
            }

            public static int max(int a1, int a2)
            {
                return a1 > a2 ? a1 : a2;
            }

      上面的这个自顶向下方法会重复的计算一些子问题,导致时间复杂度较大,想要改善的话,就增加备忘录,就是当求出那些子问题的时候,用个数据结构把它记下来,下次要用到就直接读取就行。还有一种方法是自低向上,其实原理都是一样,就是用空间换时间

            static void Main(string[] args)
            {
                int[] p = new int[] {0,1,5,8,9,10,17,17,20,24,30};
                int n=Convert.ToInt32(Console.ReadLine());
                int[] r = new int[n+1];
                r[0] = 0;
                for (int i = 1; i <= n; i++)
                {
                    r[i] = -1;
                }
                DateTime starDt = DateTime.Now;
                BottomUpCutRod(p,n,r);
                DateTime endDt = DateTime.Now;
                TimeSpan st=endDt-starDt;
                Console.WriteLine(r[n]);   //输出最优值
                Console.WriteLine(st);// 消耗时间
               
            }

            public static void BottomUpCutRod(int[] p,int n,int []r)
            {
                int q = -1;
                for (int i = 1; i <= n; i++)
                {
                    for (int j = 1; j <= i; j++)
                    {
                        q = max(q, p[j] + r[i - j]);
                    }
                    r[i] = q;
                }
            }

            public static int max(int a, int b)
            {
                return a > b ? a : b;
            }

    就这样~

  • 相关阅读:
    LintCode Python 简单级题目 488.快乐数
    LintCode Python 简单级题目 100.删除排序数组中的重复数字 101.删除排序数组中的重复数字II
    LintCode Python 简单级题目 373.奇偶分割数组
    LintCode Python 简单级题目 39.恢复旋转排序数组
    LintCode Python 简单级题目 35.翻转链表
    LintCode Python 简单级题目 451.两两交换链表中的节点
    LintCode Python 简单级题目 174.删除链表中倒数第n个节点
    aws查看官方centos镜像imageid
    linux shell脚本查找重复行/查找非重复行/去除重复行/重复行统计
    php配置优化-生产环境应用版
  • 原文地址:https://www.cnblogs.com/hezhihao/p/4021184.html
Copyright © 2011-2022 走看看