部分和问题(dfs)
部分和问题
时间限制:1000 ms | 内存限制:65535 KB
难度:2
- 描述
- 给定整数a1、a2、.......an,判断是否可以从中选出若干数,使它们的和恰好为K。
- 输入
- 首先,n和k,n表示数的个数,k表示数的和。 接着一行n个数。 (1<=n<=20,保证不超int范围)
- 输出
- 如果和恰好可以为k,输出“YES”,并按输入顺序依次输出是由哪几个数的和组成,否则“NO”
- 样例输入
-
4 13 1 2 4 7
- 样例输出
-
YES 2 4 7
- 题解:这题用动态规划应该也能写,且时间效率高,用背包写了下,果断不对,思路有问题;
1 #include<stdio.h> 2 #include<stack> 3 using namespace std; 4 int m[21],n,k; 5 stack<int>num; 6 bool dfs(int temp,int i){ 7 if(i==n)return temp==k; 8 if(dfs(temp,i+1))return true; 9 if(dfs(temp+m[i],i+1)){ 10 num.push(m[i]); 11 return true; 12 } 13 return false; 14 } 15 int main(){ 16 while(~scanf("%d%d",&n,&k)){ 17 for(int i=0;i<n;++i)scanf("%d",&m[i]); 18 if(dfs(0,0)){ 19 printf("YES\n"); 20 for(int i=0;!num.empty();i++){ 21 if(i)printf(" "); 22 printf("%d",num.top()); 23 num.pop(); 24 } 25 puts(""); 26 } 27 else printf("NO\n"); 28 } 29 return 0; 30 }
方法二:
1 #include<stdio.h> 2 const int MAXN=21; 3 int m[MAXN],anser[MAXN]; 4 int ans,k,n; 5 void dfs(int top,int num,int sum){ 6 if(sum==k){ 7 ans=1; 8 puts("YES"); 9 for(int i=0;i<num;i++){ 10 if(i)printf(" "); 11 printf("%d",anser[i]); 12 } 13 puts(""); 14 return; 15 } 16 if(num>=n||top>=n)return; 17 for(int i=top;i<n;i++){ 18 if(ans)return; 19 anser[num]=m[i]; 20 dfs(i+1,num+1,sum+m[i]); 21 } 22 } 23 int main(){ 24 while(~scanf("%d%d",&n,&k)){ 25 ans=0; 26 for(int i=0;i<n;i++)scanf("%d",m+i); 27 dfs(0,0,0); 28 if(!ans)puts("NO"); 29 } 30 return 0; 31 }