[pta]7-10 子集和问题

设集合S={x1,x2,…,xn}是一个正整数集合,c是一个正整数,子集和问题判定是否存在S的一个子集S1,使S1中的元素之和为c。试设计一个解子集和问题的回溯法,并输出利用回溯法在搜索树(按输入顺序建立)中找到的第一个解。

输入格式:

输入数据第1行有2个正整数n和c,n表示S的大小,c是子集和的目标值。接下来的1行中,有n个正整数,表示集合S中的元素。
是子集和的目标值。接下来的1 行中,有n个正整数,表示集合S中的元素。

输出格式:

输出利用回溯法找到的第一个解,以空格分隔,最后一个输出的后面有空格。当问题无解时,输出“No Solution!”。

输入样例:

在这里给出一组输入。例如:

5 10
2 2 6 5 4

输出样例:

在这里给出相应的输出。例如:

2 2 6 

参考代码:

#include <bits/stdc++.h>
using namespace std;


int n,c;
int a[1000005];
bool flag[1000005]; // 定义bool类型的数组,标记数字的使用与否;
int cnt=0,sum=0;

// 深度优先搜索函数
void dfs(int t,int w){
    if(cnt==1) // 如果已经找到一组,返回空,结束深搜;
        return; // 深度搜索的终止条件;
    if(t==n+1){
        if(w==c) // 搜索到符合条件的值,进行输出这一组解;
        {
            for(int i=1;i<=n;i++){
                if(flag[i]==1){
                    printf("%d ",a[i]);
                }
            }
            cnt++; // 找到一组cnt+1作为标记;
        }
        return;
    }
    if(w>c) // 如果已经使用的数字和大于所需,在往下搜索就不可能满足要求;
        return; // 因为往下已经不可能满足要求了,所以进行截枝,节省时间;
    
    // 左枝,即使用这个数;
    flag[t]=1; // 将这个数标记为 1,即使用该数;
    dfs(t+1,w+a[t]); // 递归深搜
    
    // 右枝,即不使用这个数;
    flag[t]=0; // 将这一数字标记为0,即没有使用这一数字;
    dfs(t+1,w); // 递归深搜
}

int main(){
    cin>>n>>c;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        sum+=a[i]; // 求数字的和;
    }
    if(sum<c) // 判断所有数字的和是不是大于所需求的数字的和,避免不必要的深搜;
        printf("No Solution!");
    else{
        dfs(1,0); // 深搜开始
        if(cnt==0) // 如果深搜没有找到合适的解,输出没有解;
            printf("No Solution!");
    }
    return 0;
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值