运筹学中的经典动态规划

简介: 运筹学中的经典动态规划

大家好,我是新来的小小编,小何同学。

//一个老年退休OI选手//

微信图片_20220422152124.gif

应我们大大老板的要求,小小编今天打算给大家带来一些在运筹学中比较基础的动态规划问题,也算在之前的小舟小编的基础上加一些东西吧!


小舟小编之前在公众号中已经简要地给大家介绍过了什么是动态规划问题,同时他也对三个比较基础的概念:阶段,状态,决策做了比较详细的解释,如果各位观众姥爷还没有看的话,可以去了解一下。


接下来就是我们大大老板给我的任务了,这也是几个比较典型的动态规划的例子,我们一起来看一下吧!


微信图片_20220422152126.jpg

No.1

Investment Problem


微信图片_20220422152129.jpg


这问题大概就是说我们有十个投资机会,有八个投资项目,我们可以在每个投资项目.上投资多个投资机会以获得相应的回报,那我们怎么才能获得最大的回报?


首先我们要知道动态规划的精髓:无后效性,就是前面做的决策并不会影响后面做的决策,也就是说我们前面的i个投资项目中花了j个投资的机会得出来的最大利益,无论我们在后面的项目中花费多少的投资机会,都不会引起前面的改变。那么很显然,我们可以推出第一-个的所有的投资方法,然后只要推出第二个,第三个,到最后一个,最后得出来解。


然后就是我们最为激动人心的coding time了!

上代码

#include<iostream>
#include<cstring>
#include<cmath>
using  namespace std;
double value[9][5] = { {0,0,0,0,0},{0,4.1,5.8,6.5,6.8}, {0,1.8,3.0,3.9,4.5},{0,1.5,2.5,3.3,3.8},{0,2.2,3.8,4.8,5.5},{0,1.3,2.4,3.2,3.9},{0,4.2,5.9,6.6,6.8},{0,2.2,3.5,4.2,4.6},{0,1.0,1.7,2.3,2.8} };
double max(double x, double y)
{
   if (x > y) return x;
   return y;
}
int main()
{    
   double dp[9][11];//前i个投资项目用j个投资数的最大价值
   memset(dp, 0, sizeof(dp));
   for (int i = 1; i <= 8; ++i)//项目
   {
       for (int j = 1; j <= 10; ++j)//到i时用了j个
       {
           for (int d = 0; d <= 4 && d <= j; ++d)//在i这里用了d个投资
           {
               for (int k = 0; k <= j - d; ++k)//前i-1个用了k个投资
               {
                   dp[i][j] = max(dp[i][j], dp[i - 1][k] + value[i][d] + 0.5 * (j - k - d));
               }
           }
       }
   }
   cout << dp[8][10];
   return 0;
}


限于今天要讲的题目可能有点多,所以说没法给

大家很详细的讲解,下面的链 接中有我们大大老

板的PPT,里面很详细的介绍了怎么得出结果,怎

么分析,如果有不懂的地方,请移步下面链接。

然后课件里面有几道类似的题目,有兴趣的观众

姥爷们也可以去动动手。



No.2

Shortest Path Problem


在动态规划中,除了这种求最大值的算法之外,还有些是要求我们去求最小值的,这个就要求我们必须在开始处理数据之前必须把所有的储存空间先格式化一遍,不过这里的储存空间并不是意味着把它们全部格式化为零,而是格式化到无穷大,正因为我们要求的是最小值,所以说无穷大,相当于是不可能的。这跟我们求最大值时,把所有的初始化为零是一-个道理。

然后我们看一下例题。


微信图片_20220422152131.png

这个题的意思就是说我们要从纽约去往洛杉矶,

中间可以途经很多其他的的地点,每两个节点之

间有一-个固定的路程长度,那么我们达到终点的

最短距离是多少呢?

我们先开始分析下,首先在我们制定数据的时候,我们把任意两个地,点之间的所有的距离都设为无穷大,这就表示这两个地点之间是不联通的,然后再通入我们输入的数据,把他们的距离再修改,如果他们的距离不是无穷大就说明他们之间是联通的。用我们定义的矩阵dp来记录两点之间的最短距离,下面的i和j所表示的是起点和终点,然后我们要做的就是不停的用k,也就是起点和终点之间可能经过的点来做松弛操作,把它们之间的最小距离,一步一步的刷新,最后得出子最优解。


但是请各位观众老爷要注意,这种算法的前面的三重循环必须有严格的顺序要求,因为如果我们一旦把循环的层次给改变,就可能导致当我们刷新-一个最优解的时候,他的子最优解并没有得出来,从而导致我们现在所求的最优解是错误的。所以请牢牢记住这一点。


下面就是我们的代码了,小何子,上代码 !

//Floyd算法,动态规划的思想,另外没有直接写入数据,因为实在是太多了。。。。。。//
include<iostream>
using namespace std;
int dp[11][11];
int min(int x, int y)
{
   if (x > y) return y;
   return x;
}
int main()
{
   int way_number;//路径的数量
   cin >> way_number;
   for (int i = 0; i <= 10; ++i)        for (int j = 0; j <= 10; ++j)            dp[i][j] = 0x3fffffff;//无穷大的话等于不通    for (int i = 1; i <= way_number; ++i)    {        int a, b, v;        cin >> a >> b >> v;
       dp[a][b] = v;
   }
   for (int i = 0; i <= 10; ++i)
       dp[i][i] = 0;
   for (int k = 1; k <= 10; ++k)
       for (int i = 1; i <= 10; ++i)
           for (int j = 1; j <= 10; ++j)
           {
               if (dp[i][j] < 0x3fffffff && dp[k][j] < 0x3fffffff)//防止爆int
                   dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
           }
   cout << dp[1][10];
   return 0;



这种求最小值的问题,本质上和那种求最大值的问题是相似的,但是我们要注意的是这种问题的初始化的方式是不同的,千万,千万,千万不能忘记了初始化。还有就是一定要把它的最初状态给修改下,-般就是在0的时候,还有的就是因为我们设置的是最大值,进行运算的时候,可能会爆掉储存的空间,所以说我们在进行预算的时候,最好加一个特判,否则也有可能会出现bug。


大大老板的课件里面还有几个跟这个比较相似的题目,各位看官老爷有兴趣的也可以去看一下。那么今天的全部内容到这里就结束了,小编也要期末复习了,可能也要隔段时间才给能大家送上新的推文吧。


相关文章
|
移动开发 算法 调度
【贪心算法】一文让你学会“贪心”(贪心算法详解及经典案例)
贪心算法是一种非常常见的算法,它的简单和高效性使其在实际应用中被广泛使用。 贪心算法的核心思想是在每一步都采取当前状态下最优的选择,而不考虑未来可能产生的影响。虽然贪心算法不能保证总是得到最优解,但在很多情况下,它可以获得很好的结果。 本篇文章将介绍贪心算法的基本概念和一些经典应用,以及如何通过贪心算法来解决一些实际问题。希望通过本文的阅读,读者可以对贪心算法有更加深刻的理解,并能够在实际问题中应用贪心算法来得到更好的解决方案。 让我们暴打贪心算法吧!
3959 0
|
6月前
|
机器学习/深度学习 算法 Java
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
这篇文章介绍了基于贪婪技术思想的Prim算法和Dijkstra算法,包括它们的伪代码描述、Java源代码实现、时间效率分析,并展示了算法的测试用例结果,使读者对贪婪技术及其应用有了更深入的理解。
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
|
9月前
|
算法 测试技术 C++
【动态规划】【数学】【C++算法】18赛车
【动态规划】【数学】【C++算法】18赛车
|
人工智能 资源调度 Java
100个经典的动态规划方程
设g’表示从起点到第i个旅店住宿一天的最少天数;f’表示从起点到第i个旅店住宿一天,在满足最小天数前提下所需要的最少费用。那么:
152 0
|
算法 Java 决策智能
0-1背包问题:动态规划的经典应用
0-1背包问题:动态规划的经典应用
380 0
|
算法 决策智能
一文带你学习,动态规划算法
背包问题(Knapsack problem)是一种组合优化的NP完全问题。 问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。 问题的名称来源于如何选择最合适的物品放置于给定背包中。
253 1
一文带你学习,动态规划算法
|
算法
算法设计与分析/数据结构与算法实验7:0-1背包问题(分支限界法)
算法设计与分析/数据结构与算法实验7:0-1背包问题(分支限界法)
284 0
算法设计与分析/数据结构与算法实验7:0-1背包问题(分支限界法)
|
算法 调度
算法基础课第八章动态规划和贪心算法
算法基础课第八章动态规划和贪心算法
126 0
算法基础课第八章动态规划和贪心算法
|
算法
算法设计与分析/数据结构与算法实验6:0-1背包问题(回溯法)
算法设计与分析/数据结构与算法实验6:0-1背包问题(回溯法)
247 0
算法设计与分析/数据结构与算法实验6:0-1背包问题(回溯法)