zcmu1381: 简单题(多重背包)

题目链接:https://acm.zcmu.edu.cn/JudgeOnline/problem.php?id=1381

题目大意

n种砝码,每种砝码重ai,有bi个,问你最小不能称的重量是多大?最大不超过8500.

范围:(a<100,b<100)

思路

背包题,有数量限制,那么就是多重背包,就是看背包能不能装满,以下两种dp方式求解01背包。

1.dp[i]表示容量为i的包能不能装满,能的话dp[i]=1。

2.dp[i]表示容量为i的包能装的最大价值,其中每个砝码的价值等于重量本身,

最后从1开始往上累加,找到第一个dp为0的,这个就是最小的不能称出的重量。

ac代码

解法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;
}

解法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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43911947/article/details/113407431
今日推荐