动态规划理解

本文详细介绍了动态规划在解决背包问题中的应用,包括01背包、完全背包和多重背包问题的二维及一维解法。通过实例解析了如何优化算法,降低时间复杂度,实现更高效的解决方案。同时,探讨了动态规划在区间DP、计数类DP、状态压缩DP以及树形DP等场景中的应用。
摘要由CSDN通过智能技术生成

背包问题

AcWing 2. 01背包问题

  1. 二维解法
    f[i][j]表示编号不超过i的体积不超过j的最大价值
    每次选择都是分成第i个选与第i个不选
    不选第i个时 f[i][j]=f[i][j-1] 选择第i个时 体积减少v[i] 价值增加w[i];
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];
int f[N][N]; //f[i][j]表示编号不超过i的体积不超过j的最大价值
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        cin >> v[i] >> w[i];
    }
    //f[0][0 - m] = 0 //  选择0件物品  价值都是0;
        for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j <= m; j++)
        {
            f[i][j] = f[i - 1][j];
            if(j>=v[i])
            f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]);
        }
    }
    cout<<f[n][m];
}
  1. 一维解法
    由二维解法推到一维解法
    若直接删除第一维 f[i][j] = f[i - 1][j];变为 f[j] = f[j]与之前等价 此行删除
    if(j>=v[i]) 则j从0-v[i]便无意义 for循环改为for (int j = v[i]; j<=m; j++)
    若这样改 这样改相当于f[i][j]=max(f[i-1][j],f[i][j-v[i]]+w[i]);则与原式不等价
    j-v[i]严格小于j 但是 j是从小到大枚举的 算f[j]的时候 f[j-v[i]]在第i层已经被计算过了
    因此j从大到小循环就可以
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];
int f[N]; //f[i][j]表示编号不超过i的体积不超过j的最大价值
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        cin >> v[i] >> w[i];
    }
    // f[0][0 - m] = 0 //  选择0件物品  价值都是0;
    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[n][m];
}

**AcWing 3. 完全背包问题
二维解法
时间复杂度O(n^3)复杂度太高(超时)

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];
int f[N][N];
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 = 0; j <= m; j++)
            {
                for (int k = 0; k * v[i] <= j; k++)
                    f[i][j] = max(f[i][j], f[i - 1][j - v[i]*k] + k * w[i]);
            }
        }
    }
    cout << f[n][m];
    return 0;
}

一维解法

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010;

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

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] << endl;

    return 0;
}


AcWing 4. 多重背包问题
AcWing 5. 多重背包问题 II
AcWing 9. 分组背包问题**

线性DP

AcWing 898. 数字三角形
AcWing 895. 最长上升子序列
AcWing 896. 最长上升子序列 II
AcWing 897. 最长公共子序列
AcWing 902. 最短编辑距离
AcWing 899. 编辑距离

区间DP

AcWing 282. 石子合并

计数类DP

AcWing 900. 整数划分

数位统计DP

AcWing 338. 计数问题

状态压缩DP

AcWing 291. 蒙德里安的梦想
AcWing 91. 最短Hamilton路径

树形DP

AcWing 285. 没有上司的舞会

记忆化搜索

AcWing 901. 滑雪

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值