题目描述

设集合S={x1,x2,…,xn}是一个正整数集合,c是一个正整数,子集和问题判定是否存在S的一个子集S1,使S1中的元素之和为c。试设计一个解子集和问题的回溯法。

输入格式:

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

输出格式:

输出子集和问题的解,以空格分隔,最后一个输出的后面有空格。当问题无解时,输出“No Solution!”。

输入样例:

5 10
2 2 6 5 4

输出样例:

2 2 6 

参考代码:

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

int n,c,sum,flag;
//n表示S的大小,c是子集和的目标值 
//sum是当前子集和的值,flag用于标志结果 
int s[N];//元素的集合 
bool ss[N];//表示是否包含当前元素 

void search(int i){

    if(i>n){//下标超过集合的大小 
        return;    
    }              

    //取数
    ss[i]=true;
    sum+=s[i];

    if(sum==c){//满足情况 
        flag=1;
        for(int j=0;j<=i;j++){
            if(ss[j]){
                cout << s[j] << " ";
            }
        }
        exit(0);//退出函数 
    }
    else if(sum<c){//继续取数
        search(i+1);
    } 

    //回溯
    ss[i]=false;
    sum-=s[i];
    search(i+1);
}

int main(){

    cin >> n >> c;

    int count=0;
    for(int i=0;i<n;i++){
        cin >> s[i];
        count+=s[i];//求集合元素的总和 
    }
    if(count<c){//不加会超时 
        cout << "No Solution!" << endl;
        return 0;
    }

    search(0);

    if(!flag){
        cout << "No Solution!" << endl;
    }

    return 0;
}

参考资料:

子集和问题【回溯算法】

8603 子集和问题(优先做)

SDUT OJ-1764 子集和问题(非递归回溯)