[DFS]部分和问题

来源:互联网 发布:淘宝紫砂壶哪家靠谱 编辑:程序博客网 时间:2024/06/06 01:25


部分和问题

时间限制:1000 ms  |  内存限制:65535 KB
难度:2
描述
给定整数a1、a2、.......an,判断是否可以从中选出若干数,使它们的和恰好为K。
输入
首先,n和k,n表示数的个数,k表示数的和。
接着一行n个数。
(1<=n<=20,保证不超int范围)
输出
如果和恰好可以为k,输出“YES”,并按输入顺序依次输出是由哪几个数的和组成,否则“NO”
样例输入
4 131 2 4 7
样例输出
YES2 4 7

简单的部分和问题,使用深度优先搜索,从a1开始按顺序决定每个数加或者不加,在全部n个数决定后再判断他们的和是不是k即可。
注意这个方法是用的是复杂度为O(2^n)的解法,效率比较低,如果想要使用高效的解法,可参考多重部分和问题,可用复杂度为O(n²)的解法实现。
具体代码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;int a[42];bool vis[42];int n,k,cnt;bool flag;void dfs(int pos){    if(cnt >= k)    {        if(cnt == k)        {            if(flag==0)            {                flag = 1;                printf("YES\n");            }            for(int i = 1; i <= n; ++i)                if(vis[i]) printf("%d ", a[i]);            printf("\n");        }        return;    }    for(int i = pos;i<=n;i++)    {        cnt += a[i];        vis[i] = 1;        dfs(i+1);        vis[i] = 0;        cnt -= a[i];    }}int main(){    while(cin>>n>>k)    {    memset(vis,0,sizeof(vis));    flag = 0;    cnt = 0;    for(int i = 1; i <= n; i++)        scanf("%d",&a[i]);    dfs(1);    if(!flag) cout<<"No"<<endl;    }}


0 0
原创粉丝点击