01背包除了求最大,还能求最小?

文章介绍了如何将01背包算法反转,用于解决CCFCSP问题中的寻找在总花费大于某个值x时,花费最小的物品组合。通过滚动数组优化,将时间复杂度降低至O(n^2v),避免了暴力搜索的高时间消耗。
摘要由CSDN通过智能技术生成

概述

做ccfcsp2022-9-2 何以包邮这一题时,发现了零一背包还能反着用,故记录一下.

01背包正常用法

借用蓝桥云课题目-小明的背包
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,v;
    cin>>n>>v;
    vector<pair<int,int>> a(n);
    for(int i=0;i<n;i++){
        cin>>a[i].first>>a[i].second;
    }
    vector<int> dp(v+1,0);
    for(int i=0;i<n;i++){
        for(int j=v;j>=0;j--){
            if(j>a[i].first)
            dp[j]=max(dp[j],dp[j-a[i].first]+a[i].second);
        }
    }
    cout<<dp[v];
}

ccfcsp-何以包邮?

在这里插入图片描述

思路

01背包一般挑选总重量不超过n的物品下使得总价值最大,但是这道题目要求挑选总花费>x的时候花费最小的情况.暴力的想法是枚举所有书的组合,找到价格大于x的最小的情况.但是时间肯定会超.我们考虑dp[i][j]是前i个物品中,能否挑选其中任意个物品,使得组合出的价值为j.当前i-1个物品能组合出价值为j-a[i]的组合时,加上当前(第i个)物品,就能组合出,价值为j的组合.当遍历完所有物品后,就是所有物品能组合出的所有价值情况.在本题目中价值就是花费,只要找到大于x的最小花费就可以了.

AC代码

#include<iostream>
#include<vector>
using namespace std;

typedef long long ll;

ll mod = 1e9 + 7;
int main()
{
    int n, x;
    cin >> n >> x;
    vector<int> a(n);
    int allv = 0;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
        allv += a[i];
    }
    //采用滚动数组,和普通背包的滚动数组一样
    vector<bool> dp(allv + 1, 0);//列是所有物品的价值总和
    dp[0]=1;//当前0个物品中能组合出价值为0的组合,这是显而易见的

    for (int i = 0; i < n; i++)//遍历所有物品
    {
        for (int j = allv; j >=a[i]; j--)
        {
            if(dp[j-a[i]]!=0){//前i-1个物品中能够凑出总价值为j-a[i]的组合
                dp[j]=true;//那么算上当前物品,在前i个物品中,能够凑出总价值为j的组合
            }

        }
    }
    for(int i=x;i<=allv;i++){
        if(dp[i]){//找到所有物品能凑出的价值大于x的第一个,就是答案
         cout<<i;
         return 0;
        }
    }

}

总结01背包的新功能

其实本质借用了01背包的模板,来求n个物品中取任意个,能组成的价值和,时间复杂度是O(n2 v),n是物品个数,v是物品平均价值.如果使用暴力搜索的话时间复杂度是O(2n ).
在做别的题的时候也遇到过这种零一背包的用法,当时只是看题解.现在总结出来之后感觉明了了很多

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值