zoukankan      html  css  js  c++  java
  • nyoj 1091 还是01背包(超大数dp)

    nyoj 1091 还是01背包

    描述

    有n个重量和价值分别为 wi 和 vi 的物品,从这些物品中挑选总重量不超过W的物品,求所有挑选方案中价值总和的最大值

    1 <= n <=40

    1 <= wi <= 10^15

    1 <= vi <= 10^15

    1 <= W <= 10^15

    分析:在做的时候毫无头绪,在网上看了其他大神的博客才AC了,数据超大无法使用之前的思路(超时且dp数组开不了这么大),但是由本题条件可知n的值非常小,可用递归配合剪枝解题

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring> 
    #define Max(a, b) a > b ? a:b
    using namespace std;
    typedef long long ll;
    const ll INF = 1000000000000000;
    ll w[45], v[45];
    ll sw[45], sv[45];
    ll n, W, ans;
    void solve(int i, ll W, ll V) {
        if(i == 0) {
            ans = Max(ans, V);
            return;    
        }
        if(W == 0 || ans >= V + sv[i]) return;//背包满或者当前总的加上这个前i个的总价值小于当前的总value,这步是剪枝 
        if(W >= sw[i]) {//因为是从上往下找的,所以只要当前容量能装下前i个的和,所以这时一定是最大的 ,剪枝 
            V += sv[i];
            ans = Max(ans, V);
            W = 0;
            return;
        }
        if(w[i] <= W) solve(i-1, W - w[i], V + v[i]);
        solve(i-1, W, V);
    }
    int main() {
        while(cin >> n >> W) {
            ans = -1;
            memset(sw, 0, sizeof(sw));
            memset(sv, 0, sizeof(sv));
            for(int i = 1; i <= n; i++) {
                cin >> w[i] >> v[i];
                sw[i] = sw[i-1] + w[i];
                sv[i] = sv[i-1] + v[i];
            }
            solve(n, W, 0);
            cout << ans << endl;
        } 
        return 0;
    } 
    作者:kindleheart
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    ArcGIS Engine 笔记-控件类型
    个人简历(公开版)
    生活垃圾处理相关
    如何让nextcloud支持avi文件在线播放
    NextCloud前端支持播放mov文件
    使用Huginn抓取Discourse论坛
    使用WordPress制作微信小程序
    Github 快速建库上传本地代码
    BestSync多终端文件资料同步利器
    ABAP-SAP HANA 数据库并发控制
  • 原文地址:https://www.cnblogs.com/kindleheart/p/8870742.html
Copyright © 2011-2022 走看看