[笔记]对动态规划的简单理解

动态规划的基本思想

个人理解:动态规划是一个先求解子问题然后逐步由子问题求解出最终问题的过程,其核心思想是“将子问题的求解结果保存”,当需要用到子问题的解时直接从读取子问题的解,而不是对子问题进行重复计算。
动态规划并不是一种具体的算法而是一种设计方法或者说是策略。

适用动态规划的问题的特征是具有重叠子问题。

下面引用来自知乎的一个回答:
quora上有这样一个问题:
How should I explain dynamic programming to a 4-year-old?
底下有个42K赞同的答案,是这样说的:
writes down "1+1+1+1+1+1+1+1 = " on a sheet of paper
“What’s that equal to?”
counting “Eight!”
writes down another "1+ " on the left
“What about that?”
quickly “Nine!”
“How’d you know it was nine so fast?”
“You just added one more”
“So you didn’t need to recount because you remembered there were eight!Dynamic
Programming is just a fancy way to say ‘remembering stuff to save time later’”
动态规划是把一个大问题拆解成一堆小问题,这个本身没啥问题,但是我觉得的这个不是动态规划的核心思想,或者说,一个”大问题“之所以能用”动态规划“解决,并不是因为它能拆解成一堆小问题,事实上啥大问题都能拆解成小问题…
取决于该问题是否能用动态规划解决的是这些”小问题“会不会被被重复调用。

大问题拆解为子问题然后求解,不是动态规划的解决问题的核心思想,而是用分治法求解问题的总体思想。动态规划的核心思想在于将子问题的解保存,这也决定了动态规划方法最适用于具有重叠子问题的问题求解
动态规划能降低时间复杂度的原因是动态规划方法不需要重复求解子问题,也就是说子问题只需求解一次,后面直接拿来用。用一小部分空间换取大部分的计算时间。问题的求解空间中将大部分的重复子问题剪掉。

对问题使用动态规划方法求解的难点在于递推关系的寻找(目前我也卡在此处)

例题:
钢条切割问题
一根钢条总长度为10
每段钢条的长度和价值对应的关系如下:
在这里插入图片描述
求如何切使钢条价值最大。
解题思路:
可以把一根钢条分为两部分 一部分是整体作为一段不切割,另一部分是由多段组合而成。其中不切割的那部分价值为V[i],由多端组合而成的那部分的价值为F(n-i)
最大价值为MAX(V[ i ] + F(n-i)),问题的解就是F(10);
求解代码:

import java.util.*;
public class B {
	static int []mf;//存放子问题的解
	static int []v;//存放不同长度的价值,比如v[2]就是长度为2的钢条的价格
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		v =  new int[n+1];
		for (int i = 1; i < v.length; i++) {
			v[i] = scanner.nextInt();
		}
		//存放子问题的解
		mf =  new int[n+1];
		//给数组初始化
		for (int i = 0; i <mf.length; i++) {
			mf[i] = -1;
		}
		mf[0] = 0;
		mf[1] = v[1];
		System.out.println(df(n));
	}
	//递归求解
	public static int df(int n) {
		if(n == 0)return 0;
		//如果之前计算过该子问题那么直接返回
		if(mf[n] != -1)return mf[n];
		//计算子问题
		int max = -1;
		for (int i = 0; i < n; i++) {
			//组合
			int temp = v[n-i] + df(i);
			if(temp > max) {
				max = temp;
			}
		}
		//将子问题的解记录
		mf[n] = max;
		return max;
	}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值