ICPC Southeast USA 2020 Regional Contest problem problem B: Bad Packing(背包dp+思维)

题目描述

We have a knapsack of integral capacity and some objects of assorted integral sizes. We attempt to fill the knapsack up, but unfortunately, we are really bad at it, so we end up wasting a lot of space that can’t be further filled by any of the remaining objects. In fact, we are optimally bad at this! 
How bad can we possibly be?
figure out the least capacity we can use where we cannot place any of the remaining objects in the knapsack. For example, suppose we have 3 objects with weights 3, 5 and 3, and our knapsack has  capacity 6. If we foolishly pack the object with weight 5 first, we cannot place either of the other two objects in the knapsack. That’s the worst we can do, so 5 is the answer.

输入

The first line of input contains two integers n (1 ≤ n ≤ 1,000) and c (1 ≤ c ≤ 105 ), where n is the number of objects we want to pack and c is the capacity of the knapsack.
Each of the next n lines contains a single integer w (1 ≤ w ≤ c). These are the weights of the objects.

输出

Output a single integer, which is the least capacity we can use where we cannot place any of the remaining objects in the knapsack.

样例输入 Copy

3 6
3
5
3

样例输出 Copy

5


 

这个题求的是:

使得没有的使用的物品中任意一个物品都无法放入背包,求一个已经使用了的背包的最小的容量

那么转化一下就是没有使用的物品中的最小值大于剩余空间

我们把物品按照从小到大排序

假设

1   2  3  4  5 

我们枚举最小值,如果这个最小值是3的话,也就是说 1 和2已经放入背包了,假设他们的和是sum,那么背包的剩余容量就是m-sum

剩余可以使用的物品是[i+1,n](因为i是最小值,我们保证i还没有放入背包,但是大于i的物品可以放)

我们用dp[i]表示用可以用的物品中能否组成质量为i的集合(值为0/1)

如果dp[i]可以组成的话,那么dp[i+sum]也一定可以组成

然后我们扫一遍背包大小,如果dp[j] =1 也就是能用的物品能组成质量为j的集合,

如果此时a[i]大于m-j(剩余容量)

就说明此时j是一个满足条件的答案,我们再所有的答案中取最小值就ok了

int n,m,a[maxn],pre[maxn],dp[maxn],ans=inf,temp[maxn];
int main() {
    n=read(),m=read();
    rep(i,1,n) a[i] = read();
    sort(a+1,a+1+n);
    rep(i,1,n)pre[i] = pre[i-1] + a[i];
    dp[0]=1;
    for(int i=n ; i>=1 ; i--) {
        int sum = pre[i-1];
        mst(temp,0);
        for(int j=0 ; j<=m ; j++) if(j+sum<=m&&dp[j]) temp[j+sum]=1;
        for(int j=1 ; j<=m ; j++ ) if(temp[j]&&a[i]>m-j) ans = min(ans,j);
        for(int j=m; j>=a[i]; j--) if(dp[j-a[i]]||dp[j]) dp[j] = 1;
    }
    if(pre[n]<=m) ans = pre[n];
    out(ans);
    return  0;
}
View Code

 

posted @ 2021-04-12 20:07  UpMing  阅读(251)  评论(0)    收藏  举报