nyoj1058 部分和问题

来源:互联网 发布:淘宝游戏币交易平台 编辑:程序博客网 时间:2024/05/21 05:22

部分和问题

时间限制: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


点击此处打开原题链接

代码实现:用深度搜索

#include <stdio.h>#include <string.h>int a[22];int mark[22];int n,k;int dfs(int i,int sum){if(sum == k) //搜索到答案时return 1;if(sum > k || i == n)  //剪枝 return 0;if(dfs(i + 1,sum))//不加的情况return 1;if(dfs(i + 1,sum + a[i])) //加的情况 {mark[i] = 1;  //标记选出数的位置 return 1;}return 0;  //加与没加都没搜到答案的情况 }int main(){while(~scanf("%d%d",&n,&k)){int i;memset(mark,0,sizeof(mark));for(i = 0;i < n;i ++ )scanf("%d",&a[i]);if(dfs(0,0)){printf("YES\n");for(i = 0;i < n;i ++ )if(mark[i])printf("%d ",a[i]);printf("\n");}elseprintf("NO\n");}return 0;} 

也可以不标记,用栈储存答案

#include <stdio.h>#include <string.h>#include <stack>using namespace std;int n,k;int a[22];stack<int> ans; //将答案存入栈 int dfs(int i,int sum){if(i == n)return sum == k;if(sum > k)return 0;if(dfs(i + 1,sum)) //没加 return 1;if(dfs(i + 1,sum + a[i])) //加了就存 {ans.push(a[i]);return 1;}return 0;}int main(){while(~scanf("%d%d",&n,&k)){for(int i = 0;i < n;i ++ )scanf("%d",&a[i]);if(dfs(0,0)){printf("YES\n");while(!ans.empty()){printf("%d ",ans.top());ans.pop();}printf("\n");}elseprintf("NO\n");}return 0;}

递归回溯

#include <stdio.h>#include <string.h>int a[25];int mark[25];int n,k;int flag ,sum;void dfs(int t){int i;if(sum == k){flag = 1;printf("YES\n");for(i = 0;i < n;i ++)if(mark[i])printf("%d ",a[i]);printf("\n");return ;}if(sum > k || t == n)return ;for(i = t;i < n;i ++ ){sum += a[i];//加上a[i] mark[i] = 1;//标记 dfs(i + 1); //搜索下一个数 sum -= a[i];//去标记 mark[i] = 0;//回溯减去 a[i]}}int main(){int i;while(~scanf("%d%d",&n,&k)){memset(mark,0,sizeof(mark));for(i = 0;i < n;i ++ )scanf("%d",&a[i]);flag = sum = 0;dfs(0);if(!flag)printf("NO\n");}return 0;}




0 0
原创粉丝点击