何以包邮?(2023寒假每日一题 15)

新学期伊始,适逢顿顿书城有购书满 x 元包邮的活动,小 P 同学欣然前往准备买些参考书。

一番浏览后,小 P 初步筛选出 n n n 本书加入购物车中,其中第 i i i 本( 1 ≤ i ≤ n 1≤i≤n 1in)的价格为 a i a_i ai 元。

考虑到预算有限,在最终付款前小 P 决定再从购物车中删去几本书(也可以不删),使得剩余图书的价格总和 m m m 在满足包邮条件( m ≥ x m≥x mx)的前提下最小。

试帮助小 P 计算,最终选购哪些书可以在凑够 x x x 元包邮的前提下花费最小?

输入格式
输入的第一行包含空格分隔的两个正整数 n n n x x x,分别表示购物车中图书数量和包邮条件。

接下来输入 n n n 行,其中第 i i i 行( 1 ≤ i ≤ n 1≤i≤n 1in)仅包含一个正整数 a i a_i ai,表示购物车中第 i i i 本书的价格。

输入数据保证 n n n 本书的价格总和不小于 x x x

输出格式
仅输出一个正整数,表示在满足包邮条件下的最小花费。

数据范围
70 % 70\% 70% 的测试数据满足: n ≤ 15 n≤15 n15
全部的测试数据满足: n ≤ 30 n≤30 n30,每本书的价格 a i ≤ 1 0 4 a_i≤10^4 ai104 x ≤ a 1 + a 2 + ⋯ + a n x≤a_1+a_2+⋯+a_n xa1+a2++an

输入样例1:

4 100
20
90
60
60

输出样例1:

110

样例1解释
购买前两本书 ( 20 + 90 20+90 20+90) 即可包邮且花费最小。

输入样例2:

3 30
15
40
30

输出样例2:

30

样例2解释
仅购买第三本书恰好可以满足包邮条件。

输入样例3:

2 90
50
50

输出样例3:

100

样例3解释
必须全部购买才能包邮。


思路:从n件商品中移除几件使得总和 > = x >= x >=x,并且总和最小。可以看做 从 n n n 件商品中取,总体积 < = <= <= 容量 ( s u m − x ) (sum - x) (sumx),的条件下,总体积最大,从而转换成 01背包 问题,最后用 s u m   − sum~ - sum  总体积 就是题目要求的答案

#include

using namespace std;

const int N = 300010, M = 35;

int n, x;
int a[M], f[N];

int main(){
    
    cin >> n >> x;
    int sum = 0;
    for(int i = 1; i <= n; i++) cin >> a[i], sum += a[i];
    
    int m = sum - x;
    for(int i = 1; i <= n; i++)
        for(int j = m; j >= a[i]; j--)
            f[j] = max(f[j], f[j - a[i]] + a[i]);
            
    cout << sum - f[m] << endl;
    
    return 0;
}

你可能感兴趣的:(寒假每日一题2023,算法,数据结构,dp,背包问题)