码迷,mamicode.com
首页 > 其他好文 > 详细

17-又见01背包

时间:2017-08-25 21:45:06      阅读:338      评论:0      收藏:0      [点我收藏+]

标签:超时   clu   观察   比较   type   html   .com   测试数据   选择   

/*                                        又见01背包
时间限制:1000 ms  |  内存限制:65535 KB
难度:3

描述
        有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W
    的物品,求所有挑选方案中物品价值总和的最大值。
      1 <= n <=100
      1 <= wi <= 10^7
      1 <= vi <= 100
      1 <= W <= 10^9

输入
    多组测试数据。
    每组测试数据第一行输入,n 和 W ,接下来有n行,每行输入两个数,代表第i个物品的wi 和 vi。
输出
    满足题意的最大价值,每组测试数据占一行。
样例输入

    4 5
    2 3
    1 2
    3 4
    2 2

样例输出

    7

来源
    飘谊系列
上传者
    TC_张友谊
*/
//http://www.cnblogs.com/chenzhiyin/p/5513258.html
//由于重量太大了,开数组绝对内存超了,有观察到价值很小,故可以转化思路反过来求,
//动态规划分析:最少要拿总价值一定,求所拿的最小质量(根据"最大能拿总重量一定,求能拿的最大价值"原理推导)

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int dp[10005];
int w[105], v[105];
int W;
int main(){
    int n;
    while(~scanf("%d%d", &n, &W)){  //超时了一下午,竟然是因为忘了取反号!!!
        int sum = 0;
        for(int i = 1; i <= n; i++){        
            scanf("%d%d", &w[i], &v[i]);
            sum += v[i];
        }    
        //初始化dp
        for(int i = 1; i <= sum; i++){    //初始化dp时对应价值位上的重量初始为最大值,注意dp[0]要保证是0
            dp[i] = 1000000005;           //不是随意设的
        }        
        for(int i = 1; i <= n; i++){
            for(int j = sum; j >= 1; j--){
                if(j >= v[i])
                    dp[j] = min(dp[j], dp[j - v[i]] + w[i]); //可以看出刚好j = v[i]时就是dp[j]和w[i]大小的的比较
                else
                    dp[j] = min(dp[j], w[i]);
            }
        }
        int big = 1;
        while(big <= sum && dp[big] <= W){
            big++;
        }
        printf("%d\n", big - 1);
    }
    return 0;
}

17-又见01背包

标签:超时   clu   观察   比较   type   html   .com   测试数据   选择   

原文地址:http://www.cnblogs.com/zhumengdexiaobai/p/7429687.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!