• 动态规划:01背包问题(使用递归方法)


    // 最优原则:不管前面的策略如何,此后的决策是是基于当前状态(由上一次决策产生)的最优决策。
    // 当最优决策序列中包含最优决策子序列时,可建立动态规划递归方法。
    // (有些问题的递归式不一定能保证最优原则,因此在求解时有必要对它进行验证。若不能保持最优原则,则不可应用动态规划方法。)
    // 在得到最优解的递归式之后,需要执行回溯以构造最优解。
    // 缺点:如果不努力地去避免重复计算,递归程序的复杂性将非常可观。
    // 方案:如果在递归程序中解决了重复计算问题时,复杂性将急剧下降。
    // 递归方程也可用迭代方程来求解,这很自然地避免了重复计算。迭代方程虽然具有相同的复杂性,不需要附加的递归栈空间,因此更快一些。

    // 15x1.cpp : Defines the entry point for the console application.

    #include "stdafx.h"
    #include <iostream.h>
    #include <stdlib.h>
    #include "dosmax.h"  // has max() and min()

    // 动态规划:0-1背包问题(使用递归方法)
    int p[6] = {0, 6, 3, 5, 4, 6}; // p 价值,多放置一个0,是为了让下标统一,方便理解和计算。
    int w[6] = {0, 2, 2, 6, 5, 4}; // w 重量
    // int x[6];
    int n = 5;  // 所有物品的数量
    int c = 10; // 实际最大总容量

    // F函数的返回值是,当前剩为余容量为y,并且当前仍有剩余物品从i到n时,的最优解。
    // i为当前检索到哪个物品的序号
    int F(int i, int y)
    {
       if (i == n) return (y < w[n]) ? 0 : p[n]; // 最终返回点,一次性比较搞定!
       if (y < w[i]) return F(i+1, y); // 如果y小于当前重量,那么只有一个选择:继续向下搜寻,看看能不能放下后面的物品
       // 如果y大于当前物品的重量w[i],就有两个选择了(虽然不能当场计算出这两个选择的值,但是没关系,让它们继续往下计算就是了):
       // 最后返回(假设当前不放入物品,y的值不变)和(假设当前放入物品,y减去当前物品的重量)的两种不同选择之后,所造成不同价值的比较结果。
       // 在i=n之前,所有的F函数代表的临时总价值,都是悬而未决的。但是一旦i=n之后,依次返回正确的值。
       // F(i+1,y) 和 F(i+1, y-w[i])+p[i],它们都是i+1时候的情况,分头进行计算,相互不依赖。层次分解,就好象是一颗二叉树(中间如果y<w[i]就只有一个节点)。
       // 最后只得出一个F的值(最优值),其余F的临时总价值,全部丢弃。
       return max(F(i+1,y), F(i+1, y-w[i])+p[i]); // 切记,返回的是物品的总价值(最大值=最优解)
    }

    void main(void)
    {
       cout << "Optimal value is ";
       cout << F(1, c) << endl;
    }

    // =============================dosmax.h=====================================================

    #ifndef dosmax_
    #define dosmax_

    template <class type>
    inline type max(type a, type b)
    {
       return (a > b)? a : b;
    }

    template <class type>
    inline type min(type a, type b)
    {
       return (a < b)? a : b;
    }

    #endif

    // ==================================================================================
    // 如果下标从0开始,那么只需要改碰到n的情况,因为没有w[n]和p[n]存在。但当前w[i]与p[i]不变。
    int p[5] = {6, 3, 5, 4, 6}; // p 价值,多放置一个0,是为了让下标统一,方便理解和计算。
    int w[5] = {2, 2, 6, 5, 4}; // w 重量
    int n = 5;  // 所有物品的数量
    int c = 10; // 实际最大总容量

    int F(int i, int y)
    {
       if (i == n-1) return (y < w[n-1]) ? 0 : p[n-1]; // cas d'arret,一次性比较搞定!
       if (y < w[i]) return F(i+1, y);
       return max(F(i+1,y), F(i+1, y-w[i])+p[i]);
    }

    void main(void)
    {
       cout << "Optimal value is ";
       cout << F(0, c) << endl;
    }

  • 相关阅读:
    ASP.NET MVC5 视图预编译
    Task(TPL)简单的实现Winform(WPF)异步
    工作三年了,该报多少工资?
    mongo笔记 // 一字一句的写下来,工作点滴片段
    旅行的意义- 2018年许愿
    用户需求调研,万里长征第一步
    软件变更控制
    源码解析-Abp vNext丨分布式事件总线DistributedEventBus
    源码解析-Abp vNext丨LocalEventBus
    技术番外篇丨Github Action CI/CD
  • 原文地址:https://www.cnblogs.com/findumars/p/2330647.html
Copyright © 2020-2023  润新知