首页 > 其他分享 >「AcWing学习记录」背包问题

「AcWing学习记录」背包问题

时间:2023-02-11 14:34:05浏览次数:84  
标签:背包 记录 int vi wi 物品 include AcWing

image

集合划分一般需要满足不重和不漏两个条件,不漏是一定要满足的,但不重不一定任何时候都要满足。

AcWing 2. 01背包问题

原题链接

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次

第 i 件物品的体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

数据范围
0 < N, V ≤ 1000
0 < vi, wi ≤ 1000

集合划分

\[f(i, j) = max(f(i-1, j), f(i-1, j-vi) + wi) \]

//二维形式
#include<iostream>
#include<algorithm>

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++)
        {
            f[i][j] = f[i - 1][j];
            if(j >= v[i]) f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);
        }
    }
    cout << f[n][m] << endl;

    return 0;
}

//f(i) 只用到了 f(i-1),并且 j 和 j-vi 都是小于等于 j 的,可以用滚动数组来优化

//一维形式(01背包问题的终极写法)
#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 = m; j >= v[i]; j--)
            f[j] = max(f[j], f[j - v[i]] + w[i]);

    cout << f[m] << endl;

    return 0;
}

AcWing 3. 完全背包问题

原题链接

有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用

第 i 种物品的体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

数据范围
0 < N, V ≤ 1000
0 < vi, wi ≤ 1000

集合划分

\[f(i, j) = \max_{0 \leq k \leq V/vi+1} f(i-1, j-vi* k) + wi* k \]

//一维形式
#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. 多重背包问题

原题链接

有 N 种物品和一个容量是 V 的背包。

第 i 种物品最多有 si 件,每件体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。

数据范围
0 < N, V ≤ 100
0 < vi, wi, si ≤ 100

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 110;

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

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> v[i] >> w[i] >> s[i];

    for(int i = 1; i <= n; i++)
        for(int j = 0; j <= m; j++)
            for(int k = 0; k <= s[i] && k * v[i] <= j; k++)
                f[i][j] = max(f[i][j], f[i - 1][j - k * v[i]] + k * w[i]);

    cout << f[n][m] << endl;
    return 0;
}

AcWing 5. 多重背包问题 II

原题链接

有 N 种物品和一个容量是 V 的背包。

第 i 种物品最多有 si 件,每件体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。

数据范围
0 < N ≤ 1000
0 < V ≤ 2000
0 < vi, wi, si ≤ 2000

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 12000;

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

int main()
{
    cin >> n >> m;

    int cnt = 0;
    for(int i = 0; i < n; i++)
    {
        int a, b, s;
        cin >> a >> b >> s;
        int k = 1;
        while(k <= s)
        {
            cnt++;
            v[cnt] = a * k;
            w[cnt] = b * k;
            s -= k;
            k *= 2;
        }
        if(s > 0)
        {
            cnt++;
            v[cnt] = a * s;
            w[cnt] = b * s;
        }
    }
    n = cnt;

    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] << endl;
    return 0;
}

AcWing 9. 分组背包问题

原题链接

有 N 组物品和一个容量是 V 的背包。

第 i 组物品有 Si 个,同一组内的物品最多只能选一个。
每件物品的体积是 vij,价值是 wij,其中 i 是组号,j 是组内编号。

求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。
输出最大价值。

数据范围
0 < N, V ≤ 100
0 < Si ≤ 100
0 < vij, wij ≤ 100

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 110;

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

int main()
{
    cin >> n >> m;

    for(int i = 1; i <= n; i++)
    {
        cin >> s[i];
        for(int j = 0; j < s[i]; j++)
            cin >> v[i][j] >> w[i][j];
    }

    for(int i = 1; i <= n; i++)
        for(int j = m; j >= 0; j--)
            for(int k = 0; k < s[i]; k++)
                if(v[i][k] <= j)
                    f[j] = max(f[j], f[j - v[i][k]] + w[i][k]);

    cout << f[m] << endl;
    return 0;
}

标签:背包,记录,int,vi,wi,物品,include,AcWing
From: https://www.cnblogs.com/YuukiAsuna/p/17041574.html

相关文章

  • 【学习记录】Linux命令缩写
    最近有空看了一点Linux的相关内容,觉得命令的英文全拼还挺有意思的,记住全拼也加深了对命令的理解,所以打算记录一下常用命令(部分)的全拼。PS:英语学计算机果然带点天然优势......
  • 洛谷 P2240 部分背包问题
    原题链接题解这道题是贪心只要按照性价比最高的取一定得到的价值最大性价比就是这堆金币的价值除以重量只需要把这些金币按性价比排序就行了最后在超出和未超出之间......
  • [SA记录] P6095 [JSOI2015]串分割
    题目首先考虑到题目要求分割出的$k$个数中最大值尽量小,所以我们分割出的$k$个数的长度尽量相同。我们令$m=\lceil\frac{n}{k}\rceil$,那么这$k$个数中,有的长度为$m......
  • LeetCode全排列AcWing842. 排列数字(/dfs)
    原题解Acwing同一个题,主要参考写法题目给定一个不含重复数字的数组nums,返回其所有可能的全排列。你可以按任意顺序返回答案。约束题解classSolution{publi......
  • Mac Pro M2安装d2l踩坑记录
    source/Users/xxx/PycharmProjects/pytorch/venv/bin/activatepipinstalld2lclang:error:theclangcompilerdoesnotsupport'faltivec',pleaseuse-maltive......
  • C++面向对象学习记录(持续更新中)
    前言C++和C语言的区别C++是C语言的超集,它在C语言的基础上新增了许多面向对象编程的特性,如类、对象、继承、多态等。因此,C++语言比C语言更加灵活、强大。另外,C++还支持模......
  • 2.10学习记录
    typora掌握了typora的基础用法,包括但不限于标题的创建和子标题的设立以及更换代码环境其中标题创建是ctrl+数字数字代表几级标题子标题无序标题:星号+空格  快捷:ctr......
  • 记录一次svn提交限制提交日志 中文冲突
    首选通过搜索找到了pre-commit这个脚本直接上手修改,最终结果如下需要的可以看一下#!/bin/bashexportLANG=zh_CN.UTF-8REPOS="$1"TXN="$2"SVNLOOK=/var/packages/......
  • AcWing 799. 最长连续不重复子序列
    (双指针算法优化)思路:暴力解法:for(inti=0;i<n;i++)for(intj=0;j<=i;j++)check(i,j);算法优化:找到某种性质,尤其注意解题过程中存在的......
  • 【算法训练营day42】01背包问题基础 LeetCode416. 分割等和子集
    LeetCode416.分割等和子集题目链接:416.分割等和子集独上高楼,望尽天涯路一开始没有想到怎么转化成01背包问题,所以直接看题解找思路慕然回首,灯火阑珊处背包的体积为......