样例输入:

4 5

1 2

2 4

3 4

4 6

// 不选当前物品:保持原样
// 选当前物品:从j-v状态继承
int new_val = f[j - v] + w;  // 选择后的新价值

if (new_val > f[j]) {
    // 找到更好的方案:完全采用新方案
    f[j] = new_val;
    g[j] = g[j - v];  // 继承:新方案数 = 来源状态的方案数
} 
else if (new_val == f[j]) {
    // 价值相等:合并方案数
    g[j] = g[j] + g[j - v];  // 原有方案 + 新继承的方案
}

初始状态

容量 j f[j] (最大价值) g[j] (方案数) 说明
0 0 1 空背包,1种方案
1 0 暂无方案
2
3
4
5

处理物品1 (体积=1, 价值=2)

容量 j 原f[j] 原g[j] 新f[j] 新g[j] 变化说明
5 0 0 0 j<1,无法选择物品1
4
3
2
1 2 1 选择物品1,从g[0]继承方案数1
0 1 0 保持不变

处理物品2 (体积=2, 价值=4)

容量 j 原f[j] 原g[j] 新f[j] 新g[j] 变化说明
5 0 4 1 选择物品2,从g[3]继承方案数1
4 选择物品2,从g[2]继承方案数1
3 选择物品2,从g[1]继承方案数1
2 选择物品2,从g[0]继承方案数1
1 2 1 2 不选物品2,保持不变
0 0 保持不变

处理物品3 (体积=3, 价值=4)

容量 j 原f[j] 原g[j] 新f[j] 新g[j] 变化说明
5 4 1 8 1 选择物品3(4+4=8>4),从g[2]继承方案数1
4 6 2 选择物品3(0+4=4<4),但j=4时选物品3实际是f[1]+4=2+4=6>4?等待,这里需要修正

修正计算过程: 对于j=4,选择物品3:需要查看j=4-3=1的状态

  • f[1] = 2, 选择物品3后新价值 = 2+4 = 6
  • 原f[4] = 4, 6>4,所以更新f[4]=6, g[4]=g[1]=1
容量 j 原f[j] 原g[j] 新f[j] 新g[j] 变化说明
5 4 1 8 1 选择物品3(f[2]=4+4=8>4),从g[2]继承方案数1
4 6 选择物品3(f[1]=2+4=6>4),从g[1]继承方案数1
3 4 选择物品3(f[0]=0+4=4=4),方案数累加:1+1=2
2 不选物品3,保持不变
1 2 2
0 0 保持不变

处理物品4 (体积=4, 价值=6)

容量 j 原f[j] 原g[j] 新f[j] 新g[j] 变化说明
5 8 1 8 2 选择物品4(f[1]=2+6=8=8),方案数累加:1+1=2
4 6 6 选择物品4(f[0]=0+6=6=6),方案数累加:1+1=2
3 4 2 4 不选物品4,保持不变
2 1 1
1 2 2
0 0 保持不变

最终结果

  • 最大价值 f[5] = 8
  • 方案数 g[5] = 2

两种达到最大价值8的方案

  1. 物品2 + 物品3:体积2+3=5,价值4+4=8
  2. 物品1 + 物品4:体积1+4=5,价值2+6=8

1 条评论

  • @ 2025-11-22 21:08:36

    太好了!

    • 1