《部分和问题》
题目来源于《挑战程序设计竞赛》穷竭搜索
标题
题目
给定整数a1,a2,a3,…,an。判断是否可以从中选出若干数,使他们的和恰好为k。
限制条件
1<=n<=20
-10^8<=ai<=10^8;
-10^8<=ai<=10^8;
样例1
输入
n=4
a={1,2,4,7}
k=13
输出
Yes
样例2
输入
n=4
a={1,2,4,7}
k=15
输出
No
题目解析
这是一个深度优先搜索问题,从a1开始决定每个数加或者不加,最终得到一棵二叉树。
而最后一层就对应着每个数的加或不加得到的和,所以最后一层有2^n个状态。
使用函数栈的递归调用,从第一层向下走,走到最后一层就是递归出口。
先返回最后一层的return语句,再依次向上返回。
最后返回(0,0)的return值。就是答案。
从第0层到第n层,二叉树共有2^n+1个节点,所以复杂度为O(2*n)
第i+1层是选择加不加第i个值
代码
#include<iostream>
#include<stack>
using namespace std;
int a[25],n,k;
int dfs(int i,int sum)
{
if(i==n)
return sum==k?1:0;//当i等于n时,返回sum是否等于k
if(dfs(i+1,sum))//不加a[i]
return 1;
if(dfs(i+1,sum+a[i]))//加上a[i]
return 1;
return 0;
//无返回值转化为0
}
int main()
{
while(cin>>n>>k)
{
int i;
for(i=0;i<n;i++)
cin>>a[i];
if(dfs(0,0))
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
}