动态规划-钢条切割--DP_1

扯犊子:急了我,我发现网上的笔试中经常会出现动态规划的题目,所以我建议各位IT程序猿,如果想去好一点的公司,这个是必须要会的。

DP:动态规划通常是用来解决最优化的问题的,在这类问题中我们通过做出一组选择来达到最优解,在做出选择的同时,通常会生成和原问题相同的子问题。当多于一个选择子集都生成相同的子问题时,DP会很有效,其关键技术就是对每个这样的子问题都保存其解,当重复出现时可以避免重复求解。递归解决f(n)= f(n-1)+f(n-2)这个问题时,用DP解决会避免很多问题的重复求解。

分治法:分治法是将原问题划分为互不相交的子问题,递归的求出他们的解,然后组合起来就是原问题的解。DP也是将原问题划分为很多子问题,但是这些子问题有重复的,DP求解问题,将子问题的解保存下来,遇到相同的子问题不必重复求解。

问题: 

   钢条切割

DP解决钢条切割的方案半伪代码

@自顶向下:
    @定义数组
	 price[];价格数组
	 length 钢条的长度
	 res[length+1]存放结果数组,0-0,1-1
	 solu[length] 切割方案的组成
	
	@初始化数组	  	
	  //此方法:前三个参数为数组,后一个参数为长度
	  intial(res,solu,price,length){
	   //定义为负无穷的目的就是说明次结果并未求出,例如res[1]=负无穷,说明长度为1的价值并未求出
	   res[0]=0,res[1~length+1]=负无穷
	   execute(res,solu,price,length)
	   }	 
	@ 执行方法 
	execute(res,solu,price,length){
	 //条件1,说明此数组已经求出结果,不必重复求
	 if(res[length] > 0)
	    return res[length];
	 //条件2,如果长度为0,直接返回结果
	 int q = res[length];
	 if(length == 0)
	    return q;
	 //长度为 1~length
	 else{
	   for(i = 1~length){
           	   
	       q = max(q,price[i-1]+execute(res,solu,price,length-i))
		   if(res[length] < q){
		      res[length] = q;
              solu[length-1] = i;		  
		   }
	   }
	}
	 
	}
@自低向上
     @定义数组
	 price[];价格数组
	 length 钢条的长度
	 res[length+1]存放结果数组,0-0,1-1
	 solu[length] 切割方案的组成
	@ 执行方法 
	execute(res,solu,price,length){
	 for(i = 1~length){
	     q = -1;
	     for(j=1~i){
		   q = Max(q,price[j]+res[i-j]);
		   if(res[i] <q){
		      res[i] = q;
			  solu[i-1]=i;
		   }
		 }
	 }
	
	 }
package dynamic.planning;

/*
 * 钢条切割:保存每种的切割方案
 */
public class CuttingBarsAll {
	public static void main(String[] args) {
		int price[] = { 1, 5, 8, 9, 10 };
		int length = 5;
		// 结果
		int res[] = new int[length + 1];
		// 切割方案
		int solu[] = new int[length];
		executeDownToTop(res, price, solu, length);

		for (int i = 0; i < res.length; i++) {
			System.out.print(res[i] + " ");
		}
		System.out.println();
		for (int i = length - 1; i >= 0;) {
			System.out.print(solu[i] + " ");
			i = i - solu[i];
		}
	}

	public static void inital(int res[], int[] price, int solu[], int length) {
		for (int i = 1; i < res.length; i++) {
			res[i] = Integer.MIN_VALUE;
		}
		System.out.println(executeTopToDown(res, price, solu, length));

		for (int i = 0; i < res.length; i++) {
			System.out.print(res[i] + " ");
		}
		System.out.println();
		for (int i = length - 1; i >= 0;) {
			System.out.print(solu[i] + " ");
			i = i - solu[i];
		}
	}

	// 自顶向下
	public static int executeTopToDown(int res[], int[] price, int solu[], int length) {
		if (res[length] > 0) {
			return res[length];
		}
		int q = res[length];
		if (length == 0)
			return q;
		else {
			/*
			 * 自顶向下5->4->3->2->1->0 要求5就要求4、3、2、1
			 * 
			 * 当长度为5时求最大的价值:切割方案1+4、2+3、3+2、4+1、5+0。
			 */

			for (int i = 1; i <= length; i++) {
				// 给定i长度的价值
				int inter1 = price[i - 1];
				int inter2 = executeTopToDown(res, price, solu, length - i);

				q = inter1 + inter2;
				if (res[length] < q) {
					res[length] = q;
					solu[length - 1] = i;
				}
			}
		}
		return q;
	}

	// 自低向上 --这个简单一点 从1开始求解,2,3,...
	public static int executeDownToTop(int res[], int[] price, int solu[], int length) {
		int q = 0;
		for (int i = 1; i <= length; i++) {
			q = -1;
			for (int j = 1; j <= i; j++) {
				q = price[j - 1] + res[i - j];
				if (q > res[i]) {
					res[i] = q;
					solu[i - 1] = j;
				}
			}

		}

		return q;
	}
}

具体的想知道跟我讨论吧 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值