《算法竞赛从入门到国奖》算法基础:动态规划-基础线性dp

💡Yupureki:个人主页

✨个人专栏:《C++》 《算法》《Linux系统编程》《高并发内存池》《MySQL数据库》

《个人在线OJ平台》


🌸Yupureki🌸的简介:


目录

[1. 台阶问题](#1. 台阶问题)

算法原理

代码实现

[2. 最大子段和](#2. 最大子段和)

算法原理

代码实现

[3. 传球游戏](#3. 传球游戏)

算法原理

代码实现


1. 台阶问题

题目链接:

P1192 台阶问题 - 洛谷

算法原理

经典的动态规划题目

1. 状态表示:

dpi表示走到第i号阶梯的方式

dpn为最终结果

2. 状态转移方程

dpi = dpi-1 + dpi-2 + ...... + dpi - k (i - k >= 0)

3. 初始化

dp0 = 1

4. 填表顺序

从左到右

代码实现

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    int n,k;cin>>n>>k;
    vector<int> dp(n + 1);
    dp[0] = 1;
    for(int i = 1;i<=n;i++)
    {
        for(int j = 1;j<=k && i - j >= 0;j++)
            dp[i] = (dp[i] + dp[i - j]) % 100003;
    }
    cout<<dp[n] % 100003;
    return 0;
}

2. 最大子段和

题目链接:

P1115 最大子段和 - 洛谷

算法原理

方法很多,但本节主要讲的是动态规划,因此我们采用动态规划的方法

1. 状态表示

dpi表示前i个元素中,以第i个元素为结尾的最长字段和

2. 状态转移方程

  • 如果dpi-1 >= 0,dpi = dpi-1 + vi
  • 如果dpi-1 < 0 ,dpi = vi

3. 初始化

dp0 = 0;

4. 填表顺序

从左向右

代码实现

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() 
{
    int n;cin>>n;
    vector<int> v(n + 1);
    for(int i = 1;i<=n;i++)
    {
        int a;cin>>a;
        v[i] = a;
    }
    vector<int> dp(n+1,-0xffffff);
    int ret = -0xffffff;
    dp[0] = 0;
    for(int i = 1;i<=n;i++)
    {
        if(dp[i-1] >= 0)
            dp[i] = dp[i-1] + v[i];
        else
            dp[i] = v[i];
        ret = max(ret,dp[i]);
    }
    cout<<ret;
    return 0;
}

3. 传球游戏

题目链接:

P1057 NOIP 2008 普及组 传球游戏 - 洛谷

算法原理

1. 状态表示

dpij 表示传i下球时,到第j个人的方式

2. 状态转移方程

第j个人可以从第j-1和第j+1个人传球

但要注意,j - 1 >= 1并且 j + 1 <= n,这里为了方便,我们将数组下标0表示第1个人

从而 j - 1 >= 0 并且 j + 1 < n

得: dpij = dpi - 1abs(j - 1) + dpi - 1(j + 1) % n;

3. 初始化

一开始,第1个人拿球,即dp00 = 1

4.填表顺序

一定要先循环次数,再循环位置。因为我们更新状态是从低次数更新高次数,也就是第一行更新第二行。因此填表顺序应该是从上往下每一行,行的顺序无所谓。

代码实现

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    int n, m; cin >> n >> m;
    vector<vector<int>> dp(m + 1, vector<int>(n));
    dp[0][0] = 1;
    for (int i = 1; i < m + 1; i++)
    {
        for (int j = 0; j < n; j++)
        {
            dp[i][j] = dp[i - 1][abs(j - 1)] + dp[i - 1][(j + 1) % n];
        }
    }
    cout << dp[m][0];
    return 0;
}
相关推荐
Dillon Dong2 小时前
【风电控制】TI TMS320F28379D 双CPU架构解析与任务分布设计
嵌入式硬件·算法·变流器·风电控制
小羊在睡觉8 小时前
力扣84. 柱状图中最大的矩形
后端·算法·leetcode·golang·go
3DVisionary8 小时前
蓝光三维扫描:医疗制造的精度焦虑怎么解
人工智能·算法·制造·蓝光三维扫描·医疗制造·三维检测·义齿检测
AI玫瑰助手8 小时前
Python函数:默认参数的定义与注意事项
开发语言·python·信息可视化
好评笔记8 小时前
机器学习面试八股——常用损失函数
人工智能·深度学习·算法·机器学习·校招
weixin_468466858 小时前
全局与局部注意力机制新手实战指南
人工智能·python·深度学习·算法·自然语言处理·transformer·注意力机制
油炸自行车8 小时前
Claude Code 错误:API Error: 400 Failed to deserialize the JSON body into the
开发语言·javascript·json·trae·claude code·api error 400
肩上风骋8 小时前
C++14特性
开发语言·c++·c++14特性
_日拱一卒9 小时前
LeetCode:994腐烂的橘子
java·数据结构·算法·leetcode·深度优先
珂朵莉MM9 小时前
第七届全球校园人工智能算法精英大赛-算法巅峰赛产业命题赛第3赛季优化题--束搜索
人工智能·算法