• 0-1背包问题


    题目描述:

    有 N 件物品和容量为 M 的背包,第 i 件物品的体积是 w[i],价值是 d[i],求解将哪些物品放入背包可以使价值总和最大,每种物品只有一件,可以选择放或者不放。(N<=3500 , M<=13000)

    第一行有两个数据,分别是 N 和 M,接下来 N 行,分别输入每件物品的体积和价值。

    样例输入

    4 6
    1 4
    2 6
    3 12
    2 7

    样例输出

    23

    看过很多大神们写的有关这个问题的解法,我来分享一种不同的解法,或者说是稍微改进了一下,即不用二维数组,有大神提到过滚动数组,原谅鄙人学识浅薄,实在转化不过来了,即用两个一维数组实现递推,至于此题涉及到的递推思想,我就不再赘述了。简单说一下,对于上例,给上面物品分别标记 A,B,C,D,思想就是当只有一个A物品时,背包容量从 1~6 的最大价值分别是4,4,4,4,4,4, 最大价值是 4 , 然后再加入一个B物品后,背包从 1~6 所能容纳的最大价值分别是 4,6,10,10,10,10,最大价值是 10,继续,三个物品,背包所能容纳的最大价值分别是4,6,12,16,18,22,最大价值是 22,再加入D物品,最大价值为 23 。状态迁移方程: F[i][j] = max(F[i-1][j],F[i-1][j-weight[i]]+value[i]);  分别代表取或不取。i-1 是上一种状态得到的结果。

    poj原题链接:

    http://poj.org/problem?id=3624

    AC代码:

    #include <iostream>
    #include <cstring>
    using namespace std;
    
    int N,M;
    
    int sum(int bag[],int bag1[],int w[],int v[])
    {
        int n = 1;
        for(int i = 1; i <= N; i++)
        {
            for(int j = 1; j <= M; j++)
            {
                if(n%2 == 1)
                {
                    if(j < w[i])
                        bag[j] = bag1[j];
                    else
                        bag[j] = max(bag1[j],bag1[j-w[i]]+v[i]);
                }
                else
                {
                    if(j < w[i])
                        bag1[j] = bag[j];
                    else
    
                        bag1[j] = max(bag[j],bag[j-w[i]]+v[i]);
                }
            }
            n++;
        }
        if(n%2 == 0)
            return bag[M];
        else
            return bag1[M];
    }
    
    int main()
    {
        cin>>N>>M;
        int value[N + 1];
        int weight[N + 1];
        int bag[M+1],bag1[M+1];
        memset(bag,0,4*(M+1));
        memset(bag1,0,4*(M+1));
        memset(weight,0,4*(N+1));
        memset(value,0,4*(N+1));
        for(int i = 1; i<=N; i++)
            cin>>weight[i]>>value[i];
        cout<<sum(bag,bag1,weight,value)<<endl;
        return 0;
    }
  • 相关阅读:
    紫微斗数诸星分级及分类
    n次独立重复试验暨伯努利试验
    信息系统项目管理师上午综合知识试题解析: 项目集治理
    三点估算和PERT技术
    自己写操作系统---bootsector篇
    硬盘分区表知识—详解硬盘MBR
    如何在自定义端口上运行 Spring Boot 应用程序?
    查询所有同学的学号、姓名、选课数、总成绩
    查询平均成绩大于60分的同学的学号和平均成绩
    查询“001”课程比“002”课程成绩高的所有学生的学号;
  • 原文地址:https://www.cnblogs.com/NikkiNikita/p/9450760.html
Copyright © 2020-2023  润新知