动态规划做题步骤

原题单链接:https://rentry.org/ozd34yrn

例题

  1. 重述问题
  2. 找到最后一步
  3. 去掉最后一步,是否能划分出子问题
  4. 考虑边界

746. 使用最小花费爬楼梯

const int N=1010;

class Solution {
public:
    int mem[N];
    int dfs(vector<int>& cost, int x)
    {
        if(mem[x])return mem[x];

        int sum=0;
        if(x==1||x==0)sum=0;
        else sum=min(dfs(cost,x-1)+cost[x-1],dfs(cost,x-2)+cost[x-2]);
        mem[x]=sum;
        return sum;
    }

    int minCostClimbingStairs(vector<int>& cost) {
        int n=cost.size();
        // int ans=dfs(cost,n);
        int f[N];
        f[0]=f[1]=0;
        for(int i=2;i<=n;i++)
        {
            f[i]=min(f[i-1]+cost[i-1],f[i-2]+cost[i-2]);
        }
        return f[n];
    }
};

300. 最长递增子序列

const int N = 3010;

class Solution {
public:
    int mem[N];
    int dfs(vector<int>& nums, int x) {
        if (mem[x])
            return mem[x];

        int res = 0;
        for (int i = 0; i < x; i++) {
            if (nums[i] < nums[x]) {
                res = max(res, dfs(nums, i) + 1);
            }
        }

        mem[x] = res;
        return res;
    }

    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        int res=-1e9;
        // for(int i=0;i<n;i++)
        // {
        //     res=max(res,dfs(nums,i)+1);
        // }
        int f[N];
        for (int i = 0; i < n; i++) {
            f[i] = 1;
            for (int j = 0; j < n; j++) {
                if (nums[j] < nums[i]) {
                    f[i] = max(f[i], f[j] + 1);
                }
            }
        }
        for(int i=0;i<n;i++)
        {
            res=max(res,f[i]);
        }
        return res;
    }
};

322. 零钱兑换

const int N = 10010;

class Solution {
public:
    int mem[N];

    int dfs(vector<int>& coins, int amount) {
        if (mem[amount])
            return mem[amount];
        int n = coins.size();
        if (amount == 0)
            return 0;
        int res = 1e9;
        for (int i = 0; i < n; i++) {
            if (amount >= coins[i])
                res = min(res, dfs(coins, amount - coins[i]) + 1);
        }
        mem[amount] = res;
        return res;
    }

    int coinChange(vector<int>& coins, int amount) {
        int n = coins.size();
        // int ans = dfs(coins, amount);
        // ans=ans==1e9?-1:ans;
        int f[N];
        memset(f, 0x3f, sizeof f);
        f[0] = 0;
        for (int i = 1; i <= amount; i++) {
            for (int j = 0; j < n; j++) {
                if(i>=coins[j])
                f[i]=min(f[i], f[i-coins[j]] + 1);
            }
        }
        return f[amount]>1e9?-1:f[amount];
    }
};

剑指 Offer 42. 连续子数组的最大和

const int N=100010;

class Solution {
public:
    int mem[N];
    int dfs(vector<int>& sales,int x)
    {
        if(x<0)return 0;
        if(mem[x])return mem[x];
        int res=-1e9;
        res=max(sales[x],dfs(sales,x-1)+sales[x]);
        mem[x]=res;
        return res;
    }

    int maxSales(vector<int>& sales) {
        int n=sales.size();
        int f[N];
        int ans=-101;
        // for(int i=0;i<n;i++)
        // {
        //     ans=max(ans,dfs(sales,i));
        // }
        f[0]=sales[0];
        for(int i=1;i<n;i++)
        {
            f[i]=max(sales[i],f[i-1]+sales[i]);
        }
        for(int i=0;i<n;i++)
        {
            ans=max(ans,f[i]);
        }
        return ans;
    }
};

343. 整数拆分

const int N=110;

class Solution {
public:
    int mem[N]={0};
    int dfs(int x)
    {
        if(mem[x])return mem[x];
        if(x==0)return 1;

        int res=0;
        for(int i=1;i<x;i++)
        {
            res=max(res,max(i*(x-i),dfs(x-i)*i));
        }
        return mem[x]=res;
    }

    int integerBreak(int n) {
        int ans;
        // ans=dfs(n);
        int dp[N];
        dp[0] = dp[1] = 1;
        for (int i = 2; i <= n; ++i) {
            for (int j = 1; j < i; ++j) {
                dp[i] = max(dp[i], max(j * (i - j), dp[i - j] * j));
            }
        }
        ans=dp[n];
        return ans;
    }
};

下期待更新的dp题单(2024.2.25编)

LCR 091. 粉刷房子 简单dp

413. 等差数列划分 如果满足等差,则f[i] = f[i – 1] + 1, 否则为0

279. 完全平方数 简单预处理,最后一步:选择某个数作为最后一个

91. 解码方法 正序dfs好写

646. 最长数对链 最长上升子序列模板 + 排序

918. 环形子数组的最大和 找找最大和 、 最小和 和 总和的关系

376. 摆动序列 考虑相邻两个数大小问题,枚举选哪个模型,dp转移可以直接01转移

2786. 访问数组中的位置使分数最大 枚举每个数选或不选,记录上的数的奇偶性,01转移 实现dfs不需要传vector的参数

213. 打家劫舍 II 考虑选不选第一个物品,可以把问题分为两个子问题

122. 买卖股票的最佳时机 II 状态机模型

368. 最大整除子集 pre数组记录路径,更新时实现记录,而不是以前的max不知道更新没更新

1105. 填充书架 枚举选哪个,转移方程有教学意义

1416. 恢复数组 枚举选哪个,集合转移

2466. 统计构造好字符串的方案数 爬楼梯

1043. 分隔数组以得到最大和 枚举选哪个,集合转移

2400. 恰好移动 k 步到达某一位置的方法数目 要对mem数组做偏移,mem[now + N][cnt] ,选其中一个的思路

1335. 工作计划的最低难度 枚举选哪个思路,集合转移

7006. 销售利润最大化 集合转移, 预处理endi,选或不选

2008. 出租车的最大盈利 选或不选

1235. 规划兼职工作 选或不选 1751. 最多可以参加的会议数目 II 类似 2054. 两个最好的不重叠活动

01转移

376. 摆动序列 考虑相邻两个数大小问题,枚举选哪个模型,dp转移可以直接01转移

2786. 访问数组中的位置使分数最大 枚举每个数选或不选,记录上的数的奇偶性

122. 买卖股票的最佳时机 II 状态机模型

1186. 删除一次得到子数组最大和 子数组最大和 + 记录删没删

2369. 检查数组是否存在有效划分 划分型dp 好像用不了记忆化搜索?

2466. 统计构造好字符串的方案数 爬楼梯

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇