欢迎光临
我们一直在努力

题解:洛谷 P2871 [USACO07DEC] Charm Bracelet S

本文分享的必刷题目是从蓝桥云课、洛谷、AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。

欢迎大家订阅我的专栏:算法题解:C++与Python实现!

附上汇总贴:算法竞赛备考冲刺必刷题(C++) | 汇总


【题目来源】

洛谷:P2871 [USACO07DEC] Charm Bracelet S – 洛谷

【题目描述】

有

N

N

N 件物品和一个容量为

M

M

M 的背包。第

i

i

i 件物品的重量是

W

i

W_i

Wi​,价值是

D

i

D_i

Di​。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。

【输入】

第一行:物品个数

N

N

N 和背包大小

M

M

M。

第二行至第

N

+

1

N+1

N+1 行:第

i

i

i 个物品的重量

W

i

W_i

Wi​ 和价值

D

i

D_i

Di​。

【输出】

输出一行最大价值。

【输入样例】

4 6
1 4
2 6
3 12
2 7

【输出样例】

23

【核心思想】

  • 问题分析:给定

    N

    N

    N 件物品,每件有重量

    W

    i

    W_i

    Wi​ 和价值

    D

    i

    D_i

    Di​,背包容量为

    M

    M

    M。每件物品只能选一次,求在总重量不超过

    M

    M

    M 的前提下,能装入背包的最大总价值。这是一个经典的01背包问题。

  • 算法选择:

    • 01背包(一维滚动数组):

      d

      p

      [

      j

      ]

      dp[j]

      dp[j] 表示背包容量为

      j

      j

      j 时的最大价值,逆序遍历容量保证每件物品只选一次

  • 关键步骤:

    • 读取输入:

      N

      ,

      M

      N, M

      N,M 和

      N

      N

      N 件物品的

      (

      W

      i

      ,

      D

      i

      )

      (W_i, D_i)

      (Wi​,Di​)

    • 初始化:

      d

      p

      [

      0..

      M

      ]

      =

      0

      dp[0..M] = 0

      dp[0..M]=0

    • 01背包递推(

      i

      i

      i 从

      1

      1

      1 到

      N

      N

      N):

      • 对于

        j

        j

        j 从

        M

        M

        M 到

        W

        i

        W_i

        Wi​ 逆序:

        • d

          p

          [

          j

          ]

          =

          max

          ⁡

          (

          d

          p

          [

          j

          ]

          ,

           

          d

          p

          [

          j

          −

          W

          i

          ]

          +

          D

          i

          )

          dp[j] = \\max(dp[j],\\ dp[j – W_i] + D_i)

          dp[j]=max(dp[j], dp[j−Wi​]+Di​)

    • 输出

      d

      p

      [

      M

      ]

      dp[M]

      dp[M]

  • 时间/空间复杂度:

    • 时间复杂度:

      O

      (

      N

      ⋅

      M

      )

      O(N \\cdot M)

      O(N⋅M)

    • 空间复杂度:

      O

      (

      M

      )

      O(M)

      O(M),一维滚动数组

  • 01背包的核心思想:

    • 选或不选:对于每件物品,只有两种状态——选(占用

      W

      i

      W_i

      Wi​ 容量,获得

      D

      i

      D_i

      Di​ 价值)或不选(不占用容量,价值不变)

    • 逆序遍历保证唯一性:容量从大到小遍历,确保

      d

      p

      [

      j

      −

      W

      i

      ]

      dp[j – W_i]

      dp[j−Wi​] 是未选第

      i

      i

      i 件物品时的状态,避免同一件物品被重复选取

    • 最优子结构:

      d

      p

      [

      j

      ]

      dp[j]

      dp[j] 仅依赖之前的状态,满足无后效性

    • 适用于"有限物品 + 容量约束 + 最大化价值"类经典背包问题
  • 【解题思路】

    【算法标签】

    #普及- #01背包

    【代码详解】

    #include <bits/stdc++.h>
    using namespace std;
    int n, m, w[4000], d[4000], dp[12890];
    int main()
    {
    cin >> n >> m; // 输入n和m
    for (int i=1; i<=n; i++) { // 输入n件无皮的重量和价值
    cin >> w[i] >> d[i];
    }
    for (int i=1; i<=n; i++) { // 01背包的模板(滚动数组版)
    for (int j=m; j>=w[i]; j—) {
    dp[j] = max(dp[j], dp[j–w[i]]+d[i]);
    }
    }
    cout << dp[m] << endl; // 输出dp[m]
    return 0;
    }

    【运行结果】

    4 6
    1 4
    2 6
    3 12
    2 7
    23

    赞(0)
    未经允许不得转载:171主机测评 » 题解:洛谷 P2871 [USACO07DEC] Charm Bracelet S
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址