买书
题目描述
小明去书店买书,他有 m 元钱,书店里面有 n 本书,每本书的价格为 pi元。小明很爱学习,想把身上钱都用来买书,并且刚好买 k 本书。请帮小明计算他是否能刚好用 m 元买 k 本书。
输入描述
第一行输入 3 个整数 m(1≤m≤100000000),n(1≤n≤30),k(1≤k≤min(8,n))
接下来一行输入 n 个整数,表示每本书的价格 pi(1≤pi≤100000000)。
输出描述
如果小明能刚好用 m 元买 k 本书,输出一行"Yes", 否则输出一行"No"。
用例输入 1
10 4 4
1 2 3 4
用例输出 1
Yes
用例输入 2
10 4 3
1 2 3 4
用例输出 2
No
思路
将问题转化为从n个数中取k个数,能否使得和为m。由于n的值很小,该问题采用DFS即可得到答案。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int tag, n, k;
bool flag = 0;
vector<int> books;
void dfs(ll sum, int start, int cnt)
{
if (cnt == k && sum == tag) // 取了k本书并且价格和为m
{
flag = 1;
return;
}
if (cnt >= k || sum > tag || start >= n) // 如果书的数量大于k本 或 价格总和大于m元 或 已遍历完n本书,终止递归
return;
for (int i = start; i < n && cnt + n - i >= k && sum + books[i] <= tag; i++)
{
dfs(sum + books[i], i + 1, cnt + 1);
if (flag) // 如果已找到符合条件的方案,终止递归
return;
}
return;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> tag >> n >> k;
vector<int> book(n);
for (int i = 0; i < n; i++)
{
cin >> book[i];
}
sort(book.begin(), book.end()); // 排序,用于后续dfs中剪枝
books = book;
dfs(0, 0, 0);
if (flag)
cout << "Yes";
else
cout << "No";
return 0;
}