CCF-CSP 202209-2 何以包邮?

CCF-CSP 202209-2 何以包邮?

  • 题目要求
    • ‍⬛题目描述
    • ‍⬛输入格式
    • ‍⬛输出格式
    • ‍⬛样例说明
      • 样例1输入
      • 样例1输出
      • 样例1解释
      • 样例2输入
      • 样例2输出
      • 样例2解释
      • 样例3输入
      • 样例3输出
      • 样例3解释
    • ‍⬛子任务
    • ‍⬛提示
  • 问题解决
    • 满分代码(含逐行代码解释)
      • C++
    • 场景拓展

题目要求

‍⬛题目描述

新学期伊始,适逢顿顿书城有购书满 x x x 元包邮的活动,小 P 同学欣然前往准备买些参考书。
一番浏览后,小 P 初步筛选出 n n n 本书加入购物车中,其中第 i i i ( 1 ≤ i ≤ n ) (1 \leq i \leq n) (1in) 的价格为 a i a_i ai 元。
考虑到预算有限,在最终付款前小 P 决定再从购物车中删去几本书(也可以不删),使得剩余图书的价格总和 m m m 在满足包邮条件 ( m ≤ x ) (m \leq x) (mx) 的前提下最小。

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

‍⬛输入格式

从标准输入读入数据。

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

接下来输入 n n n 行,其中第 i i i ( 1 ≤ i ≤ n ) (1 \leq i \leq n) (1in) 仅包含一个正整数 a i a_i ai,表示购物车中第 i i i 本书的价格。输入数据保证 n n n 本书的价格总和不小于 x x x

‍⬛输出格式

输出到标准输出。

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

‍⬛样例说明

样例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解释

必须全部购买才能包邮。

‍⬛子任务

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

‍⬛提示

对于 70% 的测试数据,直接枚举所有可能的情况即可。

问题解决

满分代码(含逐行代码解释)

C++

#include
using namespace std;

int main(){
	int n, x;
	cin >> n >> x;
	vector<int>a(31); //每本书的价格
	int sum = 0;
	for(int i = 1; i <= n; i++){
		cin >> a[i];
		sum += a[i];
	}
	int temp;
	temp = sum -x; //需要选出的书籍的价格总和
	int dp[31][100001]; //这是一个动态规划的问题
	for(int i = 1; i <= n; i++){ //外层循环遍历每本书
		for(int j = 1; j <= temp; j++){ //内层循环遍历总价值不超过temp的情况
			/*
				对于每个状态dp[i][j],有两种选择:选取第i本书或不选取
				如果不选取第i本书,则dp[i][j] = dp[i-1][j];
				如果选择第i本书,则dp[i][j] = dp[i-1][j-a[i]]+a[i],取两者之间的最大值。
			*/
			dp[i][j] = dp[i-1][j];
			if(j >= a[i]){
				dp[i][j] = max(dp[i][j], dp[i-1][j-a[i]]+a[i]);
				//dp[i][j]表示在前i本书中选取总价不超过j的最大价格
			}
		}
	}
	int result = 0;
	result = sum - dp[n][temp]; //计计算选出的书籍的价格总和,并将其减去所有书籍的价格总和
	cout << result <<endl;
	return 0;
} 

场景拓展

本题代码属于动态规划算法的题型。具体而言,这个问题可以称为「01背包问题」的变种。在「01背包问题」中,我们有一组物品,每个物品都有自己的重量和价值,目标是选择一些物品装入背包,使得背包的总重量不超过限制,并且价值最大化。而这个问题中,我们需要选择一些书籍的价格,使得总价格不超过限制,并且尽量高。

  • 0-1背包问题:给出一组物品的重量和价值,选择一些物品装入背包,使得背包的总重量不超过限制,而总价值最大化。
  • 完全背包问题:与0-1背包类似,但每种物品可以选择无限次放入背包。
  • 多重背包问题:与0-1背包类似,但每种物品有限定的可选次数。
  • 分组背包问题:将物品分为若干组,每组物品只能选择一个,目标是选择一些物品使得背包的总重量不超过限制,而总价值最大化。
  • 背包问题的变种:如带有约束条件、特殊要求或者多个限制条件的背包问题。

你可能感兴趣的:(CCF-CSP,算法,c++)