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