题目描述
​ 李华要过生日了,正好小明有两张购物券,所以他决定购买 N 件礼物送给李华。小明选好了 N 件礼物,并且总价值正好为两张购物券之和,但是结账时,小明被告知,一次只能使用一张购物券,不找零,不补现,这就意味着,小明购买的 N 件物品中,必须有若干物品的总价值正好等于其中一张购物券的价值。现求小明能不能用购物券顺利的购物。

输入
​ 有多组测试数据,对于每组测试数据:

第一行两个正整数 N,X,表示物品个数,和其中一张购物券的面额。(N≤40)

第二行输入 N 个数,分别表示物品的价格。所有物品总价格不会超过 int 范围。

输出
​ 对于每组样例输出一行,若能成功购买输出 YES,否则输出 NO。

样例输入

10 2000
1000 100 200 300 400 500 700 600 900 800
10 2001
1000 100 200 300 400 500 700 600 900 800

样例输出

YES
NO

数据规模与约定
​ 时间限制:1 s

内存限制:256 M

100% 的数据保证 N≤40

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

int n,cost,num[45], cnt[2], set[2][3000005];

void func(int set_num, int start, int end, int sum) {
if (sum > cost) return;
for (int i = start; i < end; i++) {
sum += num[i];
cnt[set_num]++;
set[set_num][cnt[set_num]] = sum;
func(set_num, i + 1, end, sum);
sum -= num[i];
}
}
int main() {
while (cin >> n >> cost) {
cnt[0] = cnt[1] = 0;
for (int i = 0; i < n; i++) {
cin >> num[i];
}
func(0, 0, n / 2, 0);
func(1, n / 2, n, 0);
sort(set[1], set[1] + cnt[1]);
int f = 0;
for (int i = 0; i < cnt[0]; i++) {
int target = cost - set[0][i];
int l = 0, r = cnt[1] - 1;
while (l <= r) {
int mid = l + (r-l) / 2;
if (set[1][mid] == target) {
cout << "YES" << endl;
f = 1;
break;
}
else if (set[1][mid] > target) {
r = mid - 1;
}
else {
l = mid + 1;
}
}
if (f == 1) break;
}
if (f == 0) {
cout << "NO" << endl;
}
}
return 0;
}