HDU 3449 Consumer 有依赖背包 分组背包 (算法有问题)

题意: 有50个盒子, 每个盒子里有10个物品, 物品有价值和花费, 盒子只有花费, 只有买了盒子才能买其中的物品, 问总共花P块钱(P<100000)最多能得到多少价值.

思路:

①一开始不记得有依赖背包, 想起之前写的挖矿的题, 以为可以直接写分组背包, 以下是错误的思路:

对于每个盒子, dfs遍历这个盒子内所有的取法, 然后每个盒子是一个分组, 跑分组背包.

复杂度: dfs后, 每个组的大小1000*分组个数50*背包容量(P)100000→5e9

下面这个思路过了, 但这不是有依赖背包的真正写法....

②因为分组背包每个组只会取1个元素, 所以dfs遍历出的1000个中, 代价大而价值小的是绝对没用的.

然而因为dfs复杂度是2^mi(mi是背包大小)所以这个思路只适合这个题...

②代码:

#include<bits/stdc++.h>

using namespace std;

void debug_out() {
    cerr << '\n';
}

template<typename T, typename ...R>
void debug_out(const T &f, const R &...r) {
    cerr << f << " ";
    debug_out(r...);
}

#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);

typedef long long ll;

const int M = 2e5 + 5;
const int inf = 1e9 + 5;
const int mod = 1e9 + 7;

int begn;
int P;
struct item {
    int prize, w;
};

struct beg {
    int sz, price;
    vector<item> v;
} Beg[55];

vector<item> V[55];

void init() {

    for (int i = 0; i < begn; i++) {
        scanf("%d%d", &Beg[i].price, &Beg[i].sz);
        for (int j = 0; j < Beg[i].sz; ++j) {
            int a, b;
            scanf("%d%d", &a, &b);
            Beg[i].v.push_back(item{a, b});
        }
    }
}

void dfs(int bgnum, int lv, int allp, int allw) {
    if (lv == Beg[bgnum].sz) {
        for (auto & i : V[bgnum]) {//这里去掉了②中提到的分组中绝对没用的元素
            if(i.prize<=allp&&i.w>=allw)
                return;
        }
        V[bgnum].push_back(item{allp, allw});
        return;
    }
    dfs(bgnum, lv + 1, allp + Beg[bgnum].v[lv].prize, allw + Beg[bgnum].v[lv].w);
    dfs(bgnum, lv + 1, allp, allw);
}

int dp[M] = {0};

void solve() {
    memset(dp, 0, sizeof(dp));
    for(int i=0;i<begn;i++){
        Beg[i].v.clear();
        V[i].clear();
    }
    for (int i = 0; i < begn; i++) {
        dfs(i, 0, Beg[i].price, 0);
    }

//    for (int i = 0; i < begn; i++) {
//        debug(V[i].size());
//    }


    for (int i = 0; i < begn; ++i) {
        for (int j = P; j >= 0; j--) {
            for (auto &k : V[i]) {
                if (j >= k.prize)
                    dp[j] = max(dp[j], dp[j - k.prize] + k.w);
            }
        }
    }
    int ans = 0;
    for (int i = 0; i <= P; ++i) {
        ans = max(ans, dp[i]);
    }
    printf("%d\n", ans);
}

int main() {
    while (~scanf("%d%d", &begn, &P)) {
        init();
        solve();
    }


    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值