描述 | |
消费者为了享受商家发布的满减优惠,常常需要面临凑单问题。 假设有n件商品,每件的价格分别为p1,p2,...,pn,每件商品最多只能买1件。为了享受优惠,需要凑单价为t。那么我们要找到一种凑单方式,使得凑单价格不小于t(从而享受优惠),同时尽量接近t。被称为“最佳凑单” 如果不存在任何一种凑单方式,使得凑单价格不小于t(即无法享受优惠),那么最佳凑单不存在。 比如当前还差10元享受满减,可选的小件商品有5件,价格分别为3元、5元、8元、8元和9元,每件商品最多只能买1件。那么当前的最佳凑单就是11元(3元+8元)。 | |
关于输入 | |
第一行输入商品数n(n<=10)和需要凑单价t,如: 5 10 第二行输入每件商品的价格,如: 3 5 8 8 9 | |
关于输出 | |
如果可以凑单成功,则输出最佳凑单的价格,如: 输入 5 10 3 5 8 8 9 输出 11 如果无法凑单成功,则输出0。 如输入 5 10 1 1 1 1 1 则无法凑够10元,输出 0 | |
例子输入 | |
5 10 3 5 8 8 9 | |
例子输出 | |
11 | |
提示 | |
1. 为了简化问题,本题中每件商品最多只能买1件。 2. 不同的商品,即使价格相同也可以都买。比如5件商品,价格分别为3元、5元、8元、8元和9元。你可以买 8元(第3件)+8元(第4件) |
做法1:k个商品凑t元=min(不选第k个 剩下k-1个凑t,选第k个 剩下k-1个凑t减去k的价值)
边界!!k=0:比较第一个商品价值与此时的额度money
#include<iostream>
using namespace std;
int value[10] = {};
int n, t;
int f(int money, int k)//挑选前k个商品,要凑的额度是money,凑单结果是返回值
{
if (k == 0 && value[0] < money)return 0;//额度没用完,也就是没凑齐,由题意返回0
if (k == 0 && value[0] >= money)return value[0];//凑齐了,返回当前凑单的值
int a = f(money, k - 1);//不选第k个产品的凑单价值
int b = f(money - value[k], k - 1) + value[k];//选第个产品的凑单价值
if (a < money && b < money)return 0;//如果都没能凑成额度,返回0
else if (a >= money && b < money)return a;//只有a可以,那么直接返回a
else if (a < money && b >= money)return b;
else if (a >= money && b >= money)return (a < b ? a : b);//都可以,返回较小的那一个
}
int main() {
cin >> n >> t;
for (int i = 1; i <= n; ++i) {
cin >> value[i];
}
cout << f(t, n);
return 0;
}
做法2:尝试所有可能的凑法并记录,再比较
#include<iostream>
#include<algorithm>
using namespace std;
int n, t, num = 0;
int cost[11] = {};
int money[200] = {};
void f(int x, int y)//第x个商品,已凑y元
{
if (y >= t) {//如果凑够了,将这种凑法的价格记录并返回
money[num++] = y;
return;
}
if (x == n) {//如果所有商品均尝试,返回
return;
}
f(x + 1, y + cost[x]);//选择第x个商品,继续凑单
f(x + 1, y);//选择第x个商品,继续凑单
}
int main()
{
cin >> n >> t;
for (int i = 0; i < n; ++i) {
cin >> cost[i];
}
f(0, 0);//从第一个商品开始凑单,初始0元
sort(money, money + num);//将所有凑单价格排序
if (money[0]) {
cout << money[0];
}
else cout << 0;
return 0;
}