1268 和为K的组合

给出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;
}

猜你喜欢

转载自blog.csdn.net/qq_38737992/article/details/79952776