动态规划--链条切割问题

钢条切割问题:给定一段长度为n英寸的钢条和一个价格表pi(i=1,2,...,n)求切割钢条方案,使得销售收益rn最大。

    注意,如果长度为n英寸的钢条的价格pn足够大,最优解可能就是完全不需要切割。

思路:先将钢条切成两条,有n-1种方案,每一种方案的最优解都等于两个子钢条的最优解。我们从这n-1个伪最优解再挑出最优的解了

以下是伪代码:

1 CUT-ROD(p,n)

2 if n == 0

3     return 0

4 q=负无穷

5 for i = 1 to n

6     q=max(q,p[i]+CUT-ROD(p,n-i))

7 return q

上面只用了分治策略,这个算法的性能是很差的T(n)=2n,在子问题的求解中很多都是重复的。

动态规划就是避免这些重复。一般有两个思路1.记录中间解

1 MEM-CUT-ROD

2 let r[0..n] be a new array

3 for i = 0 to n

4     r[i]=负无穷

5 return MEM-CUT-ROD-AUX(p,n,r)

6

7 MEM-CUT-ROD-AUX(p,n,r)

8 if r[n]>=0

9     return r[n]

10 if n==0

11     q=0

12 else q=负无穷

13     for i=1 to n

14         q=max(q,p[i]+MEM-CUT-ROD-AUX(p,n-i,r))

15 r[n]=q

16 return q

2.通过对问题求解顺序的合理安排,达到避免重复

1 BOTTOM-UP-CUT-ROD(p,n)

2 let r[0..n] be a new array

3 r[0]=0

4 for j=1 to n

5     q=负无穷

6     for i=1 to j

7         q=max(q,p[i]+r[j-i])

8     r[j]=q

9 return r[n]

下面的伪代码还保留了切割长度

1 EXTEND-BOTTOM-UP-CUT-ROD(p,n)

2 let r[0..n] and s[0..n] be new arrays

3 r[0]=0

4 for j = 1 to n

5     q=负无穷

6     for i =1 to j

7         if q < p[i]+r[j-i]

8             q=p[i]+r[j-i]

9             s[j]=i

10             r[j]=q

11 return r and s

12

13 PRINT-CUT-ROD-SOLUTION(p,n)

14 (r,s)=EXTEND-BOTTOM-UP-CUT-ROD(p,n)

15 while n >0

16     print s[n]

17     n=n-s[n]

使用动态规划方法求解的最优化问题应该具备两个要素:最优子结构和子问题重叠

c语言实现代码;

#define MinNum -200
#define MaxNum 20
#include<stdio.h>
#include<stdlib.h>
int Max(int a, int b)
{
    return a > b ? a : b;
}
int CUT_ROD(int p[],int n)
{
    int q;
    if(n == 0)
        return 0;
    q = MinNum;
    for(int i = 1 ; i <= n; i++)
    {
        q = Max(q,p[i] + CUT_ROD(p,n-i));
    }
    return q;
}
int Bottom_UP_ROD(int p[],int n , int r[])
{
    int q;
    for(int i = 1; i <= n ; i++)
        r[i] = MinNum;
    r[0] = 0;
    for(int j = 1; j <= n ; j++)
    {
        q = MinNum;
        for(int i = 1 ; i <= j ;i++)
        {
            q = Max(q,p[i] + r[j-i]);
        }
        r[j] = q;
    }
    return r[n];
}
int MEMOIZED_CUT_ROD_AUX(int p[],int n , int r[])
{
    int q;
    if(r[n] >= 0)
        return r[n];
    if(n == 0)
         q = 0;
    else
    {
        q = MinNum;
        for(int i = 1 ; i <= n ; i++)
            q = Max(q,p[i] + MEMOIZED_CUT_ROD_AUX(p,n-i,r));
    }
    r[n] = q;
    return q;
}
void MEMOIZED_CUT_ROD(int p[],int n)
{
    int r[MaxNum];
    for(int i = 1 ; i <= n ; i++)
        r[i] = MinNum;
}
void EXTEND_DOWN_UP_ROD(int r[],int s[],int p[], int n)
{
    r[0] = 0;
    for(int j = 1 ; j <= n ;j++)
    {
        int q  = MinNum;
        for(int i =1 ; i <= j ; i++)
        {
            if(q < p[i] + r[j-i])
            {
                q = p[i] + r[j-i];
                s[j] = i;
            }
        }
        r[j] = q;
    }
}
void Print_CUT_ROD_SOLUTION(int p[], int n , int s[])
{
    printf("----------------------------------\n");
    printf("长度为 %d 的切割方案为\n",n);
    while(n > 0)
    {
        printf("%3d",s[n]);
        n = n - s[n];
    }
    printf("\n");
}
int main()
{
    int p[] = {0,1,5,8,9,10,17,17,20,24};
    int r[MaxNum];
    int s[MaxNum];
    EXTEND_DOWN_UP_ROD(r,s,p,9);
    for(int i = 1; i <= 9; i++)
    {
        printf("长度为%d的收益最大为:%d\n",i,r[i]);
    }
    Print_CUT_ROD_SOLUTION(p,9,s);
    system("pause");
    return 0;
}
时间: 2024-11-01 16:01:27

动态规划--链条切割问题的相关文章

动态规划 钢条切割问题的朴素解法

第一版代码 : #include <iostream> using namespace std; int max(int a,int b) { if(a>=b)return a; else return b; } int cut_rod(int *p,int n) { int q=NULL; if(n==0)return 0; else for(int i=0;i<n;i++) { q=max(q,p[i]+cut_rod(p,n-1-i)); } return q; } int

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

动态规划通常用于解决最优化问题,在这类问题中,通过做出一组选择来达到最优解.在做出每个选择的同时,通常会生成与原问题形式相同的子问题.当多于一个选择子集都生成相同的子问题时,动态规划技术通常就会很有效,其关键技术就是对每个这样的子问题都保存其解,当其重复出现时即可避免重复求解. 钢条切割问题 Serling公司购买长钢条,将其切割为短钢条出售.切割工序本身没有成本支出.公司管理层希望知道最佳的切割方案.假定我们知道Serling公司出售一段长为i英寸的钢条的价格为pi(i=1,2,…,单位为美元

动态规划 钢条切割问题

#include <stdio.h> /* *钢条切割问题: *问题描述 假设公司出售一段长度为i英寸的钢条的价格为Pi(i = 1, 2, ...单位:美元),下面给出了价格表样例: 长度i 1 2 3 4 5 6 7 8 9 10 价格Pi 1 5 8 9 10 17 17 20 24 30 切割钢条的问题是这样的:给定一段长度为n英寸的钢条和一个价格表Pi,求切割方案,使得销售收益Rn最大. */ //假定价格一开始已经给出了,用全局的写死 #define max(x,y) (x)>

动态规划 -- 钢条切割

/* 动态规划和分治法相似,都是通过组合子问题的解来求解原问题. 但分治法是将 问题划分为互不相交的子问题,递归地求解子问题,再将它们的解组合起来,求出 原问题的解.与之相反,动态规划应用于子问题重叠的情况,即不同的子问题具有公共的 子问题.在这种情况下,分治法会做很多不必要的工作. 动态规划方法通常用来求解最优化问题,这类问题通常有很多可行解.我们希望寻找 具有最优值的解. 我们通常按照如下4个步骤来设计一个动态规划算法: · 刻画一个最优解的结构特征 · 递归地定义最优解的值 · 计算最优解

第十五章 动态规划——钢条切割

前言:动态规划的概念 动态规划(dynamic programming)是通过组合子问题的解而解决整个问题的.分治算法是指将问题划分为一些独立的子问题,递归的求解各个问题,然后合并子问题的解而得到原问题的解.例如归并排序,快速排序都是采用分治算法思想.本书在第二章介绍归并排序时,详细介绍了分治算法的操作步骤,详细的内容请参考:http://www.cnblogs.com/Anker/archive/2013/01/22/2871042.html.而动态规划与此不同,适用于子问题不是独立的情况,也

动态规划之切割钢条

1.问题描述 一公司购买长钢条,将其切为短钢条出售,假设切割没有成本,公司希望知道最佳的切割方案!假设我们知道一段长度为i的钢条的价格为pi(i = 1,2,3...),钢条长度均为整英寸,下面给出一个价格表: 长度i 1  2  3  4  5  6  7  8  9  10 价格pi 1  5  8  9  10 17 17 20 24 30 给定一长度为n的钢条和一张价格表(i =1, 2,3...n),求切割钢条的方案,使的利润最大,可以不进行切割 2.动态规划 动态规划与分治法比较类似

算法导论 动态规划 钢条切割问题的自底向上解法

正式应用动态规划. 适用于动态规划解决的问题应拥有以下两个要素: 1. 最优子结构(最佳选择) 2.子问题重叠(最终的最优解的每个分部步骤,都是当前最优的子解.与贪心算法试图通过局部最优解来组合成最优解的思想相似) 下面第一版代码中,依旧存在与上一篇第一版代码相同的问题--只能求解p数组中给出的最大限度.N>=10,代码就不能够求解出正确答案.(代码中你们都懂的- -卖个萌(O(∩_∩)O哈哈~) 主要用第一版代码记录思路. 共给出两个功能函数. Max()和Bottom_Cut_Rod(),作

NOI题库 / 2.6基本算法之动态规划 - 8471:切割回文

总时间限制:  1000ms 内存限制:  65536kB 描述 阿福最近对回文串产生了非常浓厚的兴趣. 如果一个字符串从左往右看和从右往左看完全相同的话,那么就认为这个串是一个回文串.例如,"abcaacba"是一个回文串,"abcaaba"则不是一个回文串. 阿福现在强迫症发作,看到什么字符串都想要把它变成回文的.阿福可以通过切割字符串,使得切割完之后得到的子串都是回文的. 现在阿福想知道他最少切割多少次就可以达到目的.例如,对于字符串"abaacca

编程内功修炼 - 算法

编程内功讲什么? 主要讲解以下算法: 分治法 堆排序 二叉树 动态规划 贪心算法 图 算法的作用: 算法解决了哪些问题? 互联网信息的访问检测,海量数据的管理 在一个交通图中,寻找最近的路 人类基因工程,dna有10万个基因,处理这些基因序列需要复杂的算法支持 上面的算法是我们没有接触到,或者是封装到底层的东西,那么作为程序员,在日常编码过程中会在什么地方使用算法呢? 在你利用代码去编写程序,去解决问题的时候,其实这些编码过程都可以总结成一个算法,只是有些算法看起来比较普遍比较一般,偶尔我们也会