zoukankan      html  css  js  c++  java
  • 动态规划_钢条切割问题

           问题来自<算法导论>一书,大致意思是,有一段长度为n的钢条,钢条可以被分割成不同的长度的小钢条出售,不同的小钢条对应不同的售价。如长度为1售价为1,长度为2售价为3。详见下表:


          问题分解:首先这个问题的解共有2的n-1次方,因为将n长的钢条分成1,2,3,4,...,n-1个节点,每个节点都有切于不切的两种选择。其次,每中切割方案都可以分成一段长度为i(0<=i<=n)的不再分割钢条和一段n-i的再分割钢条。其中的n-i就是一个子问题,最优解就是这两者的价值和最大的情况。即:max(Vn,Vn-1+R1,Vn-2+R2,...,V1+Rn-1,V0+Rn),其中V0 = 0,R0 = 0。即有状态转移公式:

          

          其中Rn表示n长的钢条最大的价值,Vn表示不切割的长度的钢条的售价。

          继续扯动态规划的思想,首先动态规划的关键在于重复子问题特性。因为这一特性导致了动态规划思想优于分治法,动态规划将重复子问题的解保存起来,再自底向上求解上层子问题(也可以称为子阶段,如背包问题中,我认为称为子阶段更恰当)。动态规划很仔细的安排子问题的求解顺序,即在求解一个某个子问题时,该子问题的子子问题的解都已经求的,并被保存起来了,只需从内存中读取,而无需再次求解。这就话很重要啊,这就是为什么在解目标长度为n的钢条切割问题时,要使n从1开始递增的原因了。好了,关于动态规划的思想,留些下次再扯吧,下面是程序代码。

    package com.wly.algorithmbase.dailyproblem;
    
    /**
     * 动态规划解钢条切割问题
     * 动态规划的关键在于利用重复子问题
     * @author wly
     *
     */
    public class DivideNSteel {
    
    	//对应不同长度的钢条价值,如1-1,2-2,3-5,4-7,5-9....
    	static int[] dividePriceForm = {0,1,3,12,20,22,23,24,25,28,33};
    	
    	public static void main(String[] args) {
    
    		System.out.println(solve(dividePriceForm.length));
    	}
    	
    	/**
    	 * 状态转移方程 Rn = max(Vn,V1 + Rn-1,V2 + Rn-1,V3 + Rn-3,,,,Vn-1 + R1),其中Vn表示n长的钢条不切割的价值,Rn表示长度为n的子问题的最优解
    	 * @param n
    	 * @return
    	 */
    	public static int solve(int n) {
    		int[] result = new int[n]; //用于存储各个子问题的最优解,当然这里面也包含了全局最优解result[n]
    		//将所有子问题结果都先赋值成"未知值",在自底向上求解问题的过程中,用于比较最优子问题解
    		for(int i=0;i<result.length;i++) {
    			result[i] = 0;
    		}
    		result[1]  = dividePriceForm[1];
    		
    		if(n == 0) { //如果长度为0,则直接返回
    			return 0;
    		} else {
    			//这里仔细安排的子问题的求解顺序,使在求解某个子问题时,其子子问题已经有解了
    			for(int i=1;i<n;i++) { 
    				//求解各个最优子问题表示不切割的钢条长度	
    				for(int j=1;j<=i;j++) {
    					result[i] = Math.max(result[i], result[i-j] + dividePriceForm[j]);
    				}
    			}
    		}
    		for(int i:result) {
    			System.out.print(i + " ");
    		}
    		System.out.println();
    		return result[n-1];
    	}
    }
    

          运行结果:

    0 1 3 12 20 22 24 32 40 42 44 
    44
    

          O啦~~~

          转帖请保留出处:http://blog.csdn.net/u011638883/article/details/16120505

          谢谢!!


  • 相关阅读:
    JAVA合并两个有序的单链表,合并之后的链表依然有序
    excel如何将一个单元格内容拆分成多个单元格?(用到了数据->分列)
    Navicat导入excel的xlsx文件提示无法打开文件
    Request对象实现请求转发
    MessageFormat.format()和String.format()
    使用Servlet动态生成验证码
    Http协议
    使用freemarker导出word
    java注解学习(1)注解的作用和三个常用java内置注解
    SSM_CRUD新手练习(6)分页后台控制器编写
  • 原文地址:https://www.cnblogs.com/riskyer/p/3424082.html
Copyright © 2011-2022 走看看