2021-04-25

求最值型动态规划

持续更新中、、、

基本套路

一、确定状态

最后一步
转换为子问题(子问题最优,总问题也最优)

二、转移方程

f[x] = min{dfjakfadkjf,dfjkajdkl ,jklajdflka}

三、初始条件和边界情况

f[0] = 0
如果不能,,,就、、、、、

四、计算顺序

自底向上,,将所有的值都求出来,f[0],f[1],f[M],然后从中选取最大值
递归是自顶向下,,,有很多重复,,

动态规划使用数组记录中间结果,简称备忘录,,然后这样就能避免重复计算

例题一

在这里插入图片描述

public class Solution {
    /**
     * @param coins: a list of integer
     * @param amount: a total amount of money amount
     * @return: the fewest number of coins that you need to make up
     */
    public int coinChange(int[] coins, int amount) {
       int n = coins.length;
       int[] f = new int[amount+1]; //记录f[0]---f[amount]
       int i, j;
       //initialize
       f[0] = 0;
       for(i=1; i<=amount; ++i){
            f[i] = Integer.MAX_VALUE;   //initialize to Infinity
            for(j=0; j<n; ++j){
                if(i>=coins[j] && f[i-coins[j]]!=Integer.MAX_VALUE && f[i-coins[j]]+1<f[i]){
                    f[i] = f[i-coins[j]]+1;
                }
            }
       }
       if(f[amount]==Integer.MAX_VALUE){
           return -1;
       }else{
           return f[amount];
       }
    }
}

关于那三个条件的解释:
更新f[i]的三大条件:::
(1) 最后一枚硬币不能大于当前面值A[j]
(2) 子问题本身不能是拼不出来的
f[i-A[j]] != 无穷
(3)如果子问题能拼出来,那么它用的硬币数+1,要小于原问题是才更新!

这个题目的递归解法

在这里插入图片描述

例题二 poj3616

#include <iostream>
#include <algorithm>
using namespace std;
int f[1050];
struct FJ{
	int start;
	int end;
	int efficency;
}interval[1050];
int cmp(const FJ a, const FJ b){
	if(a.start==b.start)
		return a.end<b.end;
	return a.start<b.start; 
}
int main(){
	int n,m,r;
	int i,j;
	scanf("%d%d%d",&n,&m,&r);

	for(i=0; i<m; i++){
		scanf("%d%d%d",&interval[i].start,&interval[i].end,&interval[i].efficency);
		interval[i].end += r;
	}
//	f[0]=0;

	sort(interval,interval+m,cmp);

	
	for(i=0; i<m; ++i){
		f[i] = interval[i].efficency;
		for(j=0; j<i; ++j){
			if(interval[j].end<=interval[i].start){
				f[i] = max(f[i],f[j] + interval[i].efficency);
			}
		}
	}
	cout << *max_element(f, f + m) << endl;
//	cout<<f[m-1]<<endl;
 
} 


这个题目带给我的体会是,最后那个f[m-1]不一定是最大值,得到的数组f[]不一定是递增的,,最后使用max_element函数求第一个最大值——————》为了避免重复出现最大值的情况
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨陌潇潇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值