您的位置:首页 > 其它

NYOJ1058. 部分和问题(基础DFS)

2017-07-19 16:07 375 查看
部分和问题

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

【分析】基础DFS

可以确定,k大于输入的n个数之和sum是一定无解的,因此在搜索前进行一步“剪枝”,可排除一种无解的情况。若sum<=k,则从前往后搜索,结合递归与回溯法的思想,寻找可能情况。需要注意的是,输出的解的n个数的所有排列是同一种情况,因此要做去重处理。

#include <stdio.h>
#include <string.h>
#define maxn 25
int n,k;
int a[maxn];
int vis[maxn],ret[maxn];
int suc,total;
void dfs(int cur,int sum)
{
int i;
if(sum>k)
return;
if(suc==1)
return;
if(sum==k)
{
printf("YES\n");
suc=1;
for(i=0;i<cur-1;i++)
printf("%d ",ret[i]);
printf("%d\n",ret[cur-1]);
return;
}
//从cur开始搜索即可,因保证从前向后
for(i=cur;i<n;i++)
{
if(!vis[i])
{
if(sum+a[i]>k)
continue;
vis[i]=1;
ret[cur]=a[i];
dfs(cur+1,sum+ret[cur]);
vis[i]=0;
}
}
}
int main()
{
int i;
while(scanf("%d %d",&n,&k)!=EOF)
{
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
total+=a[i];
}
if(total<k)
printf("NO\n");
else
{
memset(vis,0,sizeof(vis));
suc=0;
dfs(0,0);
if(suc==0)
printf("NO\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: