完成最优切割问题的求解

一、问题分析

1.1 问题描述

一家公司购买长钢条,将其切割成短钢条出售,假设切割本身没有成本,长度为i的短钢条的价格为Pi。那给定一段长度为n的钢条和一个价格表Pi,求钢条的切割方案使得收益Rn最大。例如某公司以单价26元买到了一批长度为10的钢条,目前各长度钢条的市场价如下表所示:

长度i

1

2

3

4

5

6

7

8

9

10

价格Pi

1

5

8

9

10

17

17

20

24

26

要求:随机生成钢条长度n和不同长度钢条的价格信息,编写程序确定一种钢条的切割方案,使公司的收益最大化。

1.2 解题思路

动态规划:
对于长度为n的钢条,我们可以先切一刀,切下长度为1-10的钢条,共10种切法,
最大收益就是切下的钢条收益和剩下钢条的最大收益之和。

钢条长度为1的最大收益计算出来,保存到dp[1]

长度为2的钢条,遍历每一种切法,收益最大的保存到dp[2]

计算长度为n的钢条的最大收益,此时dp数组已经保存了1——n-1长度钢条的最大收益
遍历这10种切法,就可以找到最大的收益

由于每种钢条长度的最大收益都被保存在数组dp中,避免了很多的重复计算

二、问题的解决方案/算法选择/设计思路

2.1 算法选择

动态规划原理

①最优子结构

用动态规划求解最优化问题的第一步就是刻画最优解的结构,如果一个问题的解结构包含其子问题的最优解,就称此问题具有最优子结构性质。因此,某个问题是否适合应用动态规划算法,它是否具有最优子结构性质是一个很好的线索。使用动态规划算法时,用子问题的最优解来构造原问题的最优解。因此必须考查最优解中用到的所有子问题。

②重叠子问题

如果递归算法反复求解相同的子问题,就称为具有重叠子问题(overlapping subproblems)性质。在动态规划算法中使用数组来保存子问题的解,这样子问题多次求解的时候可以直接查表不用调用函数递归。

2.2 设计思路

对于一个动态规划问题:

第一步先确定最优解的结构。如果一个问题的解结构包含其子问题的最优解,就称此问题具有最优子结构性质。使用动态规划算法时,用子问题的最优解来构造原问题的最优解。因此必须考查最优解中用到的所有子问题。

第二步定义最优解的计算公式

第三步根据得到的求最优解公式,计算出结果。

第四步构造出最优解。

2.3 解决方案

对于长度为n的钢条,我们可以先切一刀,切下长度为1-10的钢条,共10种切法,

最大收益就是切下的钢条收益和剩下钢条的最大收益之和。

1. 钢条长度为1的最大收益计算出来,保存到dp[1]

2. 长度为2的钢条,遍历每一种切法,收益最大的保存到dp[2]

3. 计算长度为n的钢条的最大收益,此时dp数组已经保存了1——n-1长度钢条的最大收益

   遍历这10种切法,就可以找到最大的收益

  

   由于每种钢条长度的最大收益都被保存在数组dp中,避免了很多的重复计算。

三、算法设计

3.1 设计方案图

图3-1

3.2 源代码

创建伪代码

 #include<iostream>

#include<cstring>

using namespace std;

int pi[] = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 26};

// 1. 递归求解

//int cut_rod(int n)

//{

//  if(n == 0) return 0;

//  int max_value = -1;

//  for(int i=1; i<=n; i++){

//     max_value = max(max_value, v[i]+cut_rod(n-i));

//  }

//  return max_value;

//}

// 2.动态规划

/*

对于长度为n的钢条,我们可以先切一刀,切下长度为1-10的钢条,共10种切法,

最大收益就是切下的钢条收益和剩下钢条的最大收益之和。

1. 钢条长度为1的最大收益计算出来,保存到dp[1]

2. 长度为2的钢条,遍历每一种切法,收益最大的保存到dp[2]

3. 计算长度为n的钢条的最大收益,此时dp数组已经保存了1——n-1长度钢条的最大收益

   遍历这10种切法,就可以找到最大的收益

  

   由于每种钢条长度的最大收益都被保存在数组dp中,避免了很多的重复计算,

*/

int dp[1000];

int cut_rod(int n)

{

    if(n == 0) return 0;

    int max_value = -1;

    for(int i=1; i<=n; i++){

       for(int j=1; j<=i && j<=10; j++)

           max_value = max(pi[j]+dp[i-j], max_value);   

       dp[i] = max_value;      

    }

    return max_value;

}

int main()

{

    int n;

    cin >> n;

    int re = cut_rod(n);

    cout << re << endl;

    return 0;

}

四、算法设计/求解特色及关键技术

对于长度为n的钢条,我们可以先切一刀,切下长度为1-10的钢条,共10种切法,

最大收益就是切下的钢条收益和剩下钢条的最大收益之和。

1. 钢条长度为1的最大收益计算出来,保存到dp[1]

2. 长度为2的钢条,遍历每一种切法,收益最大的保存到dp[2]

3. 计算长度为n的钢条的最大收益,此时dp数组已经保存了1——n-1长度钢条的最大收益

   遍历这10种切法,就可以找到最大的收益。

  

   由于每种钢条长度的最大收益都被保存在数组dp中,避免了很多的重复计算。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值