算法13---动态规划钢材裁剪

算法13---动态规划钢材裁剪

动态规划方法通常用来求解最优化问题。动态规划算法设计步骤:

1.刻画一个最优解的结构特征。

2.递归定义最优解的值。

3.计算最优解的值,通常采用自底向上的方法。

4.利用计算出的信息构造一个最优解。

文中给出了算法的伪代码,下面我们把递归,从顶到底,从底到顶的方法都实现一下

具体的代码如下所示

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3
  4
  5
  6
  7 #define infinity  -1  //负无穷
  8 #define len 100
  9
 10
 11
 12 int cut_rod(int p[],int n);
 13 void print_menoized_cut_rod(int p[],int n);
 14 int menoized_cut_rod_aux(int p[],int r[],int s[],int n);
 15 void bottomup_cut_rod(int p[],int r[],int s[],int n);
 16 void PrintCutRodSolution(int p[], int n);//自底向上法
 17
 18
 19 //自顶向下递归实现
 20
 21 int cut_rod(int p[],int n)
 22 {
 23     int max=infinity;
 24
 25     if (n==0)
 26     {
 27         return 0;
 28     }
 29
 30     //printf("ok,start!\n");
 31     int temp=0;
 32     for (int i = 0; i < n; i++)
 33     {
 34         temp=p[i]+cut_rod(p,n-i);
 35         if (temp>max)
 36         {
 37             max=temp;
 38         }
 39     }
 40     return max;
 41 }
 42
 43
 44 /*
 45 下面我们采取动态规划的方法来求主要有两种方法
 46 第一种方法称为带备忘的自顶向下法。此方法按照递归方式编写过程,
 47 但过程会保存每个子问题的解——用数组r[i]记录总长度为i的钢管的最大收益值。
 48 当需要一个子问题的解时,过程首先检查是否已经保存过此解,如果是,直接返回保存的值,
 49 否则递归计算这个子问题。
 50
 51   第二种方法称为自底向上法,这是动态规划的常用方法,这种方法需
 52   要我们将子问题按照规模排序,按由小到大的顺序进行求解——在本题
 53   中即按i从1到n的顺序求解。每个子问题只需求解一次,并及时把结果
 54   记录下来,以便后面调用。
 55
 56 */
 57
 58
 59 //首先先实现备忘录方法。带备忘录的自顶向下方法
 60
 61  void print_menoized_cut_rod(int p[],int n)
 62  {
 63      int r[len]={0};//记录长度为i时的最大收益
 64      int s[len]={0};//用来记录对应的切割方式
 65      for (int i = 0; i < n; i++)
 66      {
 67          r[i]=infinity;
 68      }
 69      printf("the most expensive method is \n", menoized_cut_rod_aux(p,r,s,n));
 70      printf("the way to cut as follow!\n");
 71      while(n>0)
 72      {
 73          printf("%d\t",s[n]);
 74          n-=s[n];
 75      }
 76      printf("\n");
 77  }
 78
 79
 80 int menoized_cut_rod_aux(int p[],int r[],int s[],int n)
 81 {
 82     int max;
 83     if (r[n]>=0)
 84     {
 85         return r[n];
 86     }
 87     if (n==0)
 88     {
 89         max=0;
 90     }
 91     else
 92     {
 93         max=infinity;
 94         for (int i = 0; i < n; i++)
 95         {
 96             int temp=p[i]+menoized_cut_rod_aux(p,r,s,n-i);
 97             if (temp>max)
 98             {
 99                 max=temp;
100                 s[n]=i;
101             }
102         }
103     }
104     return max;
105 }
106
107 //由底到顶的方法
108 void PrintCutRodSolution(int p[], int n)
109 {
110     int r[len]={0};
111     int s[len]={0};
112     bottomup_cut_rod(p,r,s,n);
113     printf("the most value cut method solve by bottom to up:%d\n",r[n] );
114     printf("the cut method:\n");
115     while(n>0)
116     {
117         printf("%d\t",s[n]);
118         n-=s[n];
119     }
120     printf("\n");
121 }
122
123
124 void bottomup_cut_rod(int p[],int r[],int s[],int n)
125 {
126     int max;
127     for (int i = 0; i <= n; i++)
128     {
129         max=infinity;
130         for (int j = 1; j <= n;j++)
131         {
132             if (max>p[j]+r[i-j])
133             {
134                 max=p[j]+r[i-j];
135                 s[i]=j;
136             }
137         }
138         r[i]=max;
139     }
140 }
141
142
143
144 int main()
145 {
146     int p[10]={1,5,8,9,10,17,17,20,24,30};
147     int n=4;
148     // 先递归得出结果
149     int ans=cut_rod(p,n);
150
151     printf("the most benifit is %d\n", ans);
152     // 按照从底到顶的方法
153     PrintCutRodSolution(p,n);
154     printf("\n");
155     //按照从顶到底,备忘录法
156     print_menoized_cut_rod(p,n);
157     return 0;
158 }
时间: 2024-07-30 05:15:23

算法13---动态规划钢材裁剪的相关文章

贪心算法和动态规划算法

动态规划和贪心算法都是一种递推算法 即均由局部最优解来推导全局最优解 (不从整体最优解出发来考虑,总是做出在当前看来最好的选择.) 不同点: 贪心算法 与动态规划的区别:贪心算法中,作出的每步贪心决策都无法改变,由上一步的最优解推导下一步的最优解,所以上一部之前的最优解则不作保留. 能使用贪心法求解的条件:是否能找出一个贪心标准.我们看一个找币的例子,如果一个货币系统有三种币值,面值分别为一角.五分和一分,求最小找币数时,可以用贪心法求解:如果将这三种币值改为一角一分.五分和一分,就不能使用贪心

活动选择问题(贪心算法vs动态规划)

活动选择问题贪心算法vs动态规划 基础知识 1-1动态规划 1-2贪心算法 1-3贪心算法vs动态规划 活动选择问题描述 活动选择问题最优子结构 活动选择问题算法设计 4-1贪心算法之选择最早结束活动 4-1-1递归贪心算法 4-1-2迭代的方式进行 4-2贪心算法之选择最短时长活动 4-3动态规划方法实现 4-3-1自上而下的实现 4-3-2自下而上的实现 结论 活动选择问题(贪心算法vs动态规划) 1.基础知识 在讲解活动选择问题之前,我们首先来介绍一动态规划和贪心算法的基础知识 1-1.动

算法导论--贪心算法与动态规划(活动选择问题)

活动选择问题 有一个教室,而当天有多个活动,活动时间表如下:找出最大兼容活动集!活动已按结束时间升序排序. 动态规划 采用动态规划需要满足两个条件:1.最优子结构2.子问题重叠 令Sij表示在ai结束后和aj开始前活动的集合,假定Aij为活动集合Sij的最大兼容子集,其中包含活动ak.问题变成求Sik与Skj最大兼容活动子集Aik与Akjz.我们用c[i,j]表示Sij的最优解的大小. 则c[i,j] = c[i,k]+c[k,j]+1;最后我们需要遍历所有可能的k值,找出最大的一个划分作为c[

关于贪心算法和动态规划的学习 - 背包问题为例

说到背包问题,我看到了很多分类,不同的类似问题,有不一样的解法,看到的最多的两种方式是贪心算法和动态规划,于我来说,更迫切的应该是要认识一下,这些算法的区别和相同的地方,所以这节就来找资料学习一下贪心算法和动态规划的区别. 这是找到的一个对我帮助最大的,源地址:https://www.cnblogs.com/Renyi-Fan/p/7741089.html 看之前先摘一下这几个解决方案的区别:摘自网上 "所以一个问题,该用递推.贪心.搜索还是动态规划,完全是由这个问题本身阶段间状态的转移方式决定

算法导论——动态规划

动态规划指的是一个问题可以拆分成多个小的最优子问题,并且这些子问题具有重叠,典型的如斐波那契数列:f(2)=f(1)+f(0),f(3)=f(2)+f(1),f(4)=f(3)+f(2),若使用简单的递归算法求f(4),则f(2)会被计算两次,当计算f(n)时需要计算f(n-1)和f(n-2)而f(n-1)又要计算记一次f(n-2),如此往复时间复杂度为n的指数级别,导致算法效率低下.若能够记录f(2)至f(n-1)的结果,可以保证每一级计算都是O(1)复杂度,整个算法的时间复杂度就能下降至O(

算法导论--动态规划(装配线调度)

装配线问题: 某个工厂生产一种产品,有两种装配线选择,每条装配线都有n个装配站.可以单独用,装配线1或2加工生产,也可以使用装配线i的第j个装配站后,进入另一个装配线的第j+1个装配站继续生产.现想找出通过工厂装配线的最快方法. 装配线i的第j个装配站表示为Si,j,在该站的装配时间是ai,j 如果从 Si,j装配站生产后,转移到另一个生产线继续生产所耗费的时间为ti,j 进入装配线花费时间ei,完成生产后离开装配线所耗费时间为xi 令f*表示通过生产所有路线中的最快的时间 令fi[j]表示从入

算法导论--动态规划(钢条切割)

钢条切割问题 现有一段长度为n英寸的钢条和一个价格表pi,求切割方案使销售利益最大rn最大 长度为n英寸的钢条共有2n?1种不同的切割方案,因为可以每个整英寸的位置都可以决定切割或者不切割. 为了得到rn最大,可以把这个问题分成子问题求解,先切一刀,再考虑余下的部分的最大收益即求 rn=max{pk+rn?k}(k=1,2,3-n-1), pk部分不进行继续切割,直接作为一个整体售出 ; rn?k部分继续切割,考虑所有的情况,分成子问题. 求出所有k值对应的收益最大者作为rn 也有可能不进行任何

普林斯顿公开课 算法1-3:数学模型

本节主要通过建立数学模型,来计算算法的运行时间. 公式 算法的运行时间=所有操作的开销乘以操作的次数之和 开销 下表展示了各种操作所需要的时间(单位:纳秒) 整数加法 2.1 整数乘法 2.4 整数除法 5.4 浮点加法 4.6 浮点乘法 4.2 浮点除法 13.5 sin 91.3 arctan 129.0 举例 问题 计算数据中0的个数 代码 1 2 3 4 int count = 0; for (int i= 0; i < N; i++)     if (a[i] == 0)       

1106: 零起点学算法13——求2个时间之间的分钟数

1106: 零起点学算法13--求2个时间之间的分钟数 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 4320  Accepted: 1602[Submit][Status][Web Board] Description 水题 Input 输入2行,分别是2个时间,时间小时与分钟之间用:隔开(题目包含多组测试数据) Output 输出之间的分钟数(每组测试数据一行) Sample Input 12