第十三周代码(动态规划1)(持续更新)

这篇具有很好参考价值的文章主要介绍了第十三周代码(动态规划1)(持续更新)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

动态规划第十二周也写了一部分,只不过忘记放上去了。

新的一年啦,看到这里砸个祝福:新年快乐,身体健康,考试顺利,心想事成!

第十三周代码(动态规划1)(持续更新),动态规划,算法

2024/1/6        周六

蓝桥杯2012省赛     微生物增殖(简单)

第十三周代码(动态规划1)(持续更新),动态规划,算法

【解题思路】

其实新出生半分钟吃一个是干扰项,实际上是一分钟吃一个

【参考代码】

#include <iostream>
using namespace std;
int main()
{
  // 请在此输入您的代码
  int x = 10, y = 90;
  for(int time = 1 ; time <= 60 ; time++) 
  {
        y -= x; //Y被x个x吃掉,一分钟吃一次
        if(time % 2 == 0) //Y每隔2分钟分裂一次
          y *= 2;
        
        if(time % 3 == 0) //X每隔3分钟分裂一次
          x *= 2;
  }
  cout << y;
  return 0;
}

【输出结果】 

第十三周代码(动态规划1)(持续更新),动态规划,算法

动态规划的思想

分为线性DP,状态压缩DP,数位DP,树形DP。

动态规划解题步骤

基本步骤分为以下四步

(1)转换成子问题。对于动态规划,最重要的是把一个大的问题划分成若干子问题,即进行问题降阶,通过逐级降阶将问题简化,从而实现问题的求解。

(2)转移方程,把问题方程化。

(3)按照实际逻辑设置边界情况和初始条件。

(4)确定计算顺序并求解。

动态规划与分治法最大的差别

适合于用动态规划法求解的问题, 经分解后得到的子问题往往不是互相孤立的

(即下一子问题的求解是建立在上一子问题的解的基础上而进行的进一步求解)。

经典实例

背包问题

01背包问题

题目链接

题目:有一个背包可以装一定重的物品,如何装物品才能使得背包的价值最大? 背包能装的重量是 10 斤,可以装的物品有以下几种:

    矿泉水(重5斤,价值 10)

    书(重3斤,价值5)

    小吃(重4斤,价值 8)

    水果(重4斤,价值 9)

    相机(重2斤,价值6)

请问:携带哪些物品时价值最高?

【参考代码】:

#include <iostream>
using namespace std;
#include <iomanip> //用于setw函数



int main()
{
    int n, m;  //物品个数,背包总重量
    int value[100][100];
    int v[100], w[100];
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> w[i] >> v[i];  //重量,价值

    for (int j = 0; j <= m; j++)
        value[0][j] = 0;

    for (int i = 1; i <= n; i++)
    {
        value[i][0] = 0;
        for (int j = 1; j <= m; j++)
        {
             value[i][j] = value[i - 1][j];
             if (j >= w[i])
                 //状态转移方程
                 value[i][j] = max(value[i - 1][j], value[i - 1][j - w[i]] + v[i]);
        }
    }
    cout << "01背包各状态转换表:" << endl;
    for (int i = 0; i <= n; i++)
    {
        for (int j = 0; j <= m; j++)
             cout << setw(3) << value[i][j]; //隔3格输出
        cout << endl;
    }

    cout << "背包能装的最大价值为:" << value[n][m];

}

【运行结果】:

第十三周代码(动态规划1)(持续更新),动态规划,算法

优化后的01背包:

#include <iostream>
using namespace std;

int f[1001], v[1001], w[1001];

int main()
{
	int n, m;  //物品个数,背包总重量
	
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		cin >> v[i] >> w[i];  //体积,价值
	
	for (int i = 1; i <= n; i++)
	{
		for (int j = m; j >= v[i]; j--)
		{
			//状态转移方程
			f[j] = max(f[j], f[j - v[i]] + w[i]);
		}
	}

	cout << f[m];
}

 第十三周代码(动态规划1)(持续更新),动态规划,算法

第十三周代码(动态规划1)(持续更新),动态规划,算法

完全背包问题

题目链接

第十三周代码(动态规划1)(持续更新),动态规划,算法

第十三周代码(动态规划1)(持续更新),动态规划,算法

【参考代码】:

#include <iostream>
using namespace std;

int n, m, f[1001], v[1001], w[1001];

int main(){
    cin >> n >> m;
    for(int i=1; i <= n; i++)
    {
        cin >> v[i] >> w[i];
    }
    for(int i=1; i <= n; i++)
        for(int j = v[i]; j <= m; j++)
        {
            f[j] = max(f[j], f[j - v[i]] + w[i]);
        }
    cout << f[m];
}

【输出结果】

第十三周代码(动态规划1)(持续更新),动态规划,算法

多重背包

题目链接

第十三周代码(动态规划1)(持续更新),动态规划,算法

第十三周代码(动态规划1)(持续更新),动态规划,算法

参考代码

#include <iostream>
using namespace std;

int n, m, f[1001], v[1001], w[1001], l[1001];

int main()
{
    cin >> n >> m;
    for(int i=1; i <= n; i++)
        cin >> v[i] >> w[i] >> l[i];
    for(int i=1; i <= n; i++)
        for(int k=1; k <= l[i]; k++)
            for(int j=m; j>= v[i]; j--)
                f[j] = max(f[j], f[j - v[i]] + w[i]);
    cout << f[m];
        
}

【输出结果】:

第十三周代码(动态规划1)(持续更新),动态规划,算法

分组背包

题目链接

第十三周代码(动态规划1)(持续更新),动态规划,算法

第十三周代码(动态规划1)(持续更新),动态规划,算法

【参考代码】

此代码未通过100%题目测试点

#include <iostream>
#include <vector>
using namespace std;

//ai, bi, ci, 物品重量,利用价值,所属组数
int a[1001], v[1001], w[1001], f[1001];
vector<int> c[1001];

int main()
{
    //两个数m, n,表示一共有n件物品,总重量为m
    int m, n;
    cin >> m >> n;
    int i, j;
    for(i = 1; i <= n; i++)
    {
        cin >> w[i] >> v[i] >> a[i];
        c[a[i]].push_back(i);
    }
    for(i = 1; i <= 1000; i++)
        for(j = m; j; j--)
            for(auto k : c[i])
            {
                if(v[k] <= j)
                    f[j] = max(f[j], f[j - v[k]] + w[k]);
            }
    cout << f[m];
}

for(auto k : c[i]) 是一个基于范围的for循环,在C++中常见。这里是对它的分解:

  • auto: 这是一个自动类型推导关键字。在基于范围的for循环中,编译器会自动从c[i]中获取元素类型,并推断出k的类型。
  • k: 这是循环中当前元素的临时变量名。在每次循环迭代时,k将持有c[i]中的一个元素。
  • for(auto k : c[i]): 整体而言,这个循环从c[i]作为起点开始遍历中的每一个元素,并将每个元素赋值给变量k

二维背包

爬楼梯

题目链接

第十三周代码(动态规划1)(持续更新),动态规划,算法

第十三周代码(动态规划1)(持续更新),动态规划,算法

参考代码:
int jumpFloor(int number) {
        if(number == 1)
            return 1;
        if(number == 2)
            return 2;
        return jumpFloor(number - 1) + jumpFloor(number - 2);
}

第十三周代码(动态规划1)(持续更新),动态规划,算法

第十三周代码(动态规划1)(持续更新),动态规划,算法

斐波那契数列的实际应用

石子合并(区间DP)

题目链接

第十三周代码(动态规划1)(持续更新),动态规划,算法

第十三周代码(动态规划1)(持续更新),动态规划,算法

【参考代码】

#include <bits/stdc++.h>
using namespace std;

long long a[201] = {0}, s[201] = {0}, f[201][201]; // 定义数组a、s和f

// 递归函数solve,用于计算最小分割代价
long long solve(int l, int r)
{
    if(f[l][r] != -1) // 如果已经计算过该子问题的解,直接返回结果
       return f[l][r];
	if(l == r) // 如果左右边界相等,说明只有一个元素,不需要分割,返回0
		return 0;
	long long ans = 1 << 30; // 初始化最小分割代价为一个较大的值 2的30次方
	for(int m = l; m < r; m++) // 遍历所有可能的分割点m
	// 计算左右两部分的最小分割代价,并取较小值
		ans = min(ans, solve(l, m) + solve(m+1, r)); 
	return f[l][r] = ans + s[r] - s[l-1]; // 将计算得到的最小分割代价存储到f数组中,并返回结果
}

int main()
{
    memset(f, 255, sizeof(f)); // 初始化f数组为-1,表示未计算过任何子问题的解
	int n;
	cin >> n; 
	for(int i=1; i<=n; i++) 
	{
		cin >> a[i];
		s[i] = s[i-1] + a[i]; // 计算前缀和数组s
	}
    cout << solve(1, n); // 调用solve函数计算最小分割代价,并输出结果
	//cout << f[1][n]; 这个就是最终答案
}

f[1][n]是最终答案,可以看到矩形右上角为最终答案f[1][n]

第十三周代码(动态规划1)(持续更新),动态规划,算法

Q:9是怎么来的?

A:在5和3之间选一个最小值,前缀和数组是1,3,6。加上前缀和数组的最大值6

  1. ans = min(ans, solve(l, m) + solve(m+1, r));
  2. return f[l][r] = ans + s[r] - s[l-1];

第十三周代码(动态规划1)(持续更新),动态规划,算法

Q:14怎么来的?

A:5和7选一个最小值,得出5。前缀和数组是1,3,6,10。f[2][4] = 14 = 5 + 10 (s[r]) – 1 (s[l-1])

9和14选一个最小值,加上前缀和数组的最大值10

  1. ans = min(ans, solve(l, m) + solve(m+1, r));
  2. return f[l][r] = ans + s[r] - s[l-1];
  • 可以看出,若不加终止条件,会调用很多次递归函数,多次重复计算。优化后,用一个二维数组保存

最长公共子序列

题目链接

第十三周代码(动态规划1)(持续更新),动态规划,算法

第十三周代码(动态规划1)(持续更新),动态规划,算法

参考代码
class Solution {
public:
    int lengthOfLIS(vector<int>& nums)
     {
        //最长上升子序列
        int ans = 0;
        int dp[2501] = {0};
        int n = nums.size();
        //需要从0开始,不然会报错:爆栈
        for(int i=0; i < n; i++)
        {
            dp[i] = 1;
            for(int j=0; j < i; j++)
            {
                if(nums[j] < nums[i])
                    dp[i] = max(dp[i], dp[j] + 1);
            }
        }

        for(int i=0; i < n; i++)
        {
            ans = max(ans, dp[i]);
        }
        return ans;
    }
};

第十三周代码(动态规划1)(持续更新),动态规划,算法

最长公共子序列

题目链接

第十三周代码(动态规划1)(持续更新),动态规划,算法

第十三周代码(动态规划1)(持续更新),动态规划,算法

参考代码
class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int n = text1.length();
        int m = text2.length();
        int f[1001][1001];
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= m; j++)
            {
                f[i][j] = max(f[i - 1][j], f[i][j - 1]);
                if(text1[i-1] == text2[j-1]) //i, j从1开始,string从1开始,要减1
                //if(text1[i] == text2[j])
                    f[i][j] = max(f[i][j], f[i - 1][j - 1] + 1);
            }
        }
        return f[n][m];
    }
};
运行结果

第十三周代码(动态规划1)(持续更新),动态规划,算法文章来源地址https://www.toymoban.com/news/detail-789323.html

最长回文子串

到了这里,关于第十三周代码(动态规划1)(持续更新)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法通关第十九关-青铜挑战理解动态规划

    大家好我是苏麟 , 今天聊聊动态规划 . 动态规划是最热门、最重要的算法思想之一,在面试中大量出现,而且题目整体都偏难一些对于大部人来说,最大的问题是不知道动态规划到底是怎么回事。很多人看教程等,都被里面的状态子问题、状态转移方程等等劝退了。 其实,所

    2024年02月03日
    浏览(27)
  • 算法第十五期——动态规划(DP)之各种背包问题

    目录 0、背包问题分类 1、 0/1背包简化版 【代码】 2、0/ 1背包的方案数 【思路】

    2023年04月09日
    浏览(31)
  • 【夜深人静学数据结构与算法 | 第十篇】动态规划

    目录 前言: 动态规划: 常见应用: 解题步骤:  动态规划的简化步骤: 案例: 509. 斐波那契数 - 力扣(LeetCode) 70. 爬楼梯 - 力扣(LeetCode) 62. 不同路径 - 力扣(LeetCode) 总结:         本文我们将为大家讲解一下动态规划的理论知识,并且会讲解几道力扣的经典例题。

    2024年02月11日
    浏览(47)
  • 【夜深人静学习数据结构与算法 | 第十二篇】动态规划——背包问题

      目录  前言:  01背包问题: 二维数组思路: 一维数组思路: 总结:       在前面我们学习动态规划理论知识的时候,我就讲过要介绍一下背包问题,那么今天我们就来讲解一下背包问题。 在这里我们只介绍 01背包 ,至于分组背包和混合背包这种的已经属于竞赛级别的

    2024年02月12日
    浏览(37)
  • 【动态规划】动态规划算法基本概念,原理应用和示例代码

             动态规划(Dynamic Programming,简称DP)是一种解决多阶段决策问题的数学优化方法。它将原问题分解成若干个子问题,通过解决子问题只需解决一次并将结果保存下来,从而避免了重复计算,提高了算法效率。         通俗来讲,动态规划算法是解决一类具有重叠

    2024年01月21日
    浏览(36)
  • 【Matlab】动态规划算法代码记录

    简单记录一下学习Matlab过程中的代码。 参考资料:0-1背包问题 参考资料:清华学霸总结的动态规划4步曲,仅这篇动归够了

    2024年02月16日
    浏览(27)
  • 动态规划算法:原理、示例代码和解析

    动态规划算法是一种常用的优化问题解决方法,它可以应用于许多计算机科学和其他领域的问题。动态规划算法的基本思想是将一个大问题分解成多个子问题,并将每个子问题的解存储在一个表中。通过计算表中的值,可以得到最终问题的解。在本文中,我们将介绍动态规划

    2024年02月02日
    浏览(30)
  • 【算法】动态规划 ⑦ ( LeetCode 55. 跳跃游戏 | 算法分析 | 代码示例 )

    LeetCode 55. 跳跃游戏 : https://leetcode.cn/problems/jump-game/ 给定一个 非负整数数组 nums ,你最初位于数组的 第一个下标 0 位置 。 数组中的每个元素 代表你在该位置可以 跳跃的最大长度。 判断你 是否能够到达最后一个下标。 给定一个一维数组 , 数组元素不能有负数 , 如 : {2, 2,

    2024年02月10日
    浏览(29)
  • 代码随想录算法训练51 | 动态规划part12

    本题加了一个冷冻期,状态就多了,有点难度,大家要把各个状态分清,思路才能清晰  视频讲解: 动态规划来决定最佳时机,这次有冷冻期!| LeetCode:309.买卖股票的最佳时机含冷冻期_哔哩哔哩_bilibili 代码随想录 相对122.买卖股票的最佳时机II ,本题只需要在计算卖出操

    2024年01月18日
    浏览(47)
  • 【算法】算法学习七:动态规划 | 背包问题 | 最长公共子串(含源代码)

    背包问题是一种经典的组合优化问题,通常有两个版本:0-1背包问题和无限背包问题。 0-1背包问题是指给定一个背包容量和一组物品,每个物品有自己的重量和价值,要求在不超过背包容量的情况下,选择一些物品放入背包,使得物品的总价值最大化。每个物品只能选择放入

    2024年02月09日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包