★、背包求方案数的时候,多重背包是不行的,因为产生重复的背包会有多种情况。

★、背包记录路径的时候,其实是不行的,因为更新了12的最优解,如果它依赖于6这个背包,然后你后面改变了6这个背包,就GG

 

1、01背包问题。

tot:总背包空间,vall[i]:每件物品的价值,w[i]:每件物品的重量

http://acm.hdu.edu.cn/showproblem.php?pid=2602

01背包明显可以只写一维的,所以二维的就不写了。

关于为什么可以只写一维的呢?这就和你枚举的顺序有关了。从tot 枚举 到 w[i]。那么是优先更新dp[比较大的数]

而且是从dp[i - 1][]那里更新过来的。至于后面枚举小的背包容量的时候,较大的背包容量是用不了的了,所以这里就可以避免有重复使用的bug。确保都是从dp[i-  1]枚举过来。而这个顺序反转了的话,刚好的完全背包的最优解。这个后面再说

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 1e3 + 20;
int dp[maxn];
int w[maxn], val[maxn];
void work() {
    memset(dp, 0, sizeof dp);
    int n, tot;
    scanf("%d%d", &n, &tot);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &val[i]);
    }
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &w[i]);
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = tot; j >= w[i]; --j) {
            dp[j] = max(dp[j], dp[j -w[i]] + val[i]);
        }
    }
    printf("%d\n", dp[tot]);
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    int t;
    scanf("%d", &t);
    while (t--) work();
    return 0;
}
View Code

相关文章:

猜你喜欢
  • 2021-05-30
  • 2022-12-23
  • 2021-09-07
  • 2022-12-23
  • 2022-12-23
  • 2021-08-19
相关资源
相似解决方案