给出N个正整数组成的数组A,求能否从中选出若干个,使他们的和为K。如果可以,输出:"Yes",否则输出"No"。
Input
第1行:2个数N, K, N为数组的长度, K为需要判断的和(2 <= N <= 20,1 <= K <= 10^9) 第2 - N + 1行:每行1个数,对应数组的元素A[i] (1 <= A[i] <= 10^6)
Output
如果可以,输出:"Yes",否则输出"No"。
Input示例
5 13 2 4 6 8 10
Output示例
No
这道题我本来想的是全排列一下,然后分别取前1,2,3,...n 位,暴力求解,但是显然不行因为1,2 和 2,1结果一样。
这个想法可以优化,全排列是分别以 n个点 为起点去深搜,这里显然可以用一个点去深搜。
但是还是不行,因为1,3,2 和 1, 2, 3 结果是一样的, 还要再进行优化只从大于自身的点去深搜。
语言表达能力不太清楚,下面举个例子:
用 1, 2, 3, 4 去构成 10, 应该这样去深搜,深搜过程:
第一步 二 三 四 五
1 2 3 4
1 2 4
1 3 4
1 4
0 2 3 4
2 4
3 4
4
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 25; int a[N]; // 存储数组 bool flag = 0; // flag = 1 存在和为K的组合 int K; void dfs(int k, int n, int ans) { // n 为数组长度 if(ans == K){ // 存在和为K的组合 flag = 1; } if(flag || ans > K) // 已找到存在解或 ans > n(ans只能增大),在搜素下去无意义 return ; for(int i=k+1; i<=n && !flag; i++){ dfs(i, n, ans+a[i]); } } int main() { int n; cin >> n >> K; for(int i=1; i<=n; i++) { cin >> a[i]; } flag = 0; dfs(0, n, 0); // 开始搜索 if( flag ) cout << "Yes" << endl; else cout << "No" << endl; return 0; }