AcWing 8.二维费用的背包问题

实质上就是对于01背包的问题再加上了一个条件而已。

给出两种做法:

第一、DFS,超时。

在dfs中,我们在判断条件的时候千万不要分开判断条件,这样会造成误判,因为这里有两个限制条件,我们如果考虑了两种或者三种,也不一定对,会出现不必要的bug,我们直接写满足容量足够并且重量足够的条件就行了,就省了判断比较坏的情况了。其他的思路也就是和01背包是一样的。

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<cmath> 
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<sstream>
#include<map>
#include<limits.h>
#include<set>
#define MAX 1005
#define int long long
#define _for(i,a,b) for(int i=a;i<(b);i++)
#define ALL(x) x.begin(),x.end()
using namespace std;
int n, M, res, V;
int v[MAX];
int m[MAX];
int w[MAX];
int f[MAX];//前i个菜之后剩余j元
int g[MAX];
int dfs(int u, int sumV, int sumM) {
    if (u > n)
        return 0;
    else {
        if (sumM >= m[u] && sumV >= v[u])
            return max(dfs(u + 1, sumV, sumM), dfs(u + 1, sumV - v[u], sumM - m[u]) + w[u]);
        else
            return dfs(u + 1, sumV, sumM);
    }
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    cin >> n >> V >> M;
    _for(i, 1, n + 1) {
        cin >> v[i] >> m[i] >> w[i];
    }
    res = dfs(1, V, M);
    cout << res;
    return 0;
}

第二种、记忆化搜索

如果你开一个三维的空间的话,按照题目的数据范围,这个数组绝对会暴空间。

第三种、DP

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<cmath> 
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<sstream>
#include<map>
#include<limits.h>
#include<set>
#define MAX 1005
#define int long long
#define _for(i,a,b) for(int i=a;i<(b);i++)
#define ALL(x) x.begin(),x.end()
using namespace std;
int n, M, res, V;
int v[MAX];
int m[MAX];
int w[MAX];
int g[MAX];
int f[MAX][MAX];
int dfs(int u, int sumV, int sumM) {
    if (u > n)
        return 0;
    else {
        if (sumM >= m[u] && sumV >= v[u])
            return max(dfs(u + 1, sumV, sumM), dfs(u + 1, sumV - v[u], sumM - m[u]) + w[u]);
        else
            return dfs(u + 1, sumV, sumM);
    }
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    cin >> n >> V >> M;
    for (int i = 1; i <= n;i++) {
        cin >> v[i] >> m[i] >> w[i];
    }
    for (int i = 1; i <= n; i++) {
        for (int j = V; j >= v[i]; j--) {
            for (int k = M; k >= m[i]; k--) {
                    f[j][k] = max(f[j - v[i]][k - m[i]] + w[i], f[j][k]);
            }
        }
    }
    cout << f[V][M];
    return 0;
}

这里就不细讲了,也就是01背包的模板思路。

有人会问,在循环那里的判断条件为什么没有了呢?注意看循环里面的判断条件,这里我已经改成了v[i]和m[i],也就是说,我们在循环里面就已经判断了这个条件了,也就不需要再分支了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值