zcmu1381: Simple questions (multiple backpacks)

Title link: https://acm.zcmu.edu.cn/JudgeOnline/problem.php?id=1381

Topic

There are n kinds of weights, each weight is ai, there are bi. What is the smallest weight that you cannot weigh? The maximum does not exceed 8500.

Range: (a<100,b<100)

Ideas

Backpack problem, there is a limit on the number, then it is a multiple backpack, it depends on whether the backpack can be full, the following two dp methods to solve the 01 backpack.

1. dp[i] indicates whether the package with capacity i can be filled, if it can, dp[i]=1.

2.dp[i] represents the maximum value that a bag with a capacity of i can hold, where the value of each weight is equal to the weight itself,

Finally, start from 1 and add up to find the first dp of 0. This is the smallest weight that cannot be weighed.

ac code

Solution 1:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e4 + 5;
int dp[maxn], s; //dp[i]表示容量为i的包能否装满, s是最大容量
void bag1(int w){ //01背包
    for(int i = s; i >= w; i --)
        if(dp[i - w]) dp[i] = 1; //i-w能装满的话,加上此时的w,那么也能装满i
}
void bag3(int w, int num){ //多重背包
    int k = 1;
    while(k <= num){
        bag1(w * k); //分成多个01背包
        num -= k;
        k <<= 1;
    }
    bag1(w * num); 
}
int weight[maxn], num[maxn]; //weight表示砝码重量,num表示砝码数量
int main(){
    int n;
    while(~scanf("%d", &n)){
        if(n == 0) break;
        s = 0;
        memset(dp, 0, sizeof(dp));
        dp[0] = 1; //容量为0的包肯定装得满,本身就算满
        for(int i = 1; i <= n; i ++){
            scanf("%d%d", &weight[i], &num[i]);
            s += weight[i] * num[i];
        }
        for(int i = 1; i <= n; i ++){
            bag3(weight[i], num[i]); //多重背包
        }
        int id = 1;
        while(dp[id]) id ++; //dp[id]==1说明装满了
        printf("%d\n", id);
    }
    return 0;
}

Solution 2:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e5 + 5;
int dp[maxn], s; //dp[i]表示容量为i的包能获得最大价值,s是最大容量
void bag1(int w, int v){ //01背包
    for(int i = s; i >= w; i --)
        dp[i] = max(dp[i], dp[i - w] + v); 
}
void bag3(int w, int v, int num){ //多重背包
    int k = 1;
    while(k <= num){
        bag1(w * k, v * k);
        num -= k;
        k <<= 1;
    }
    bag1(w * num, v * num);
}
int weight[maxn], num[maxn];
int main(){
    int n;
    while(~scanf("%d", &n)){
        if(n == 0) break;
        s = 0;
        memset(dp, 0, sizeof(dp));
        for(int i = 1; i <= n; i ++){
            scanf("%d%d", &weight[i], &num[i]);
            s += weight[i] * num[i];
        }
        for(int i = 1; i <= n; i ++){
            bag3(weight[i], weight[i], num[i]); //价值就是重量本身
        }
        int id = 1;
        while(dp[id] == id) id ++; //最大价值等于重量说明装满了
        printf("%d\n", id);
    }
    return 0;
}

 

Guess you like

Origin blog.csdn.net/weixin_43911947/article/details/113407431