子集和問題 及 c++ 代碼實現

   首先聲明:子集和問題可以用動態規劃問題解決,即01揹包問題的解法即可。在這裏我們採用下構造樹的問題。

問題:

      給定n個正整數{wi|i=0...n}和一個正整數m,在這n個正整數中找出一個子集,使得子集中的正整數之和等於m。

 

解的形式:

      設定一個n元組(x0,x1,...xn-1),如果wi包含在這個子集中,x是解向量,xi就等於1,反之等於0.

X數組是解向量,t=∑(1,..,k-1)Wi*Xi, r=∑(k,..,n)Wi    (說明:t就是前k-1個數選擇之後的和,r表示剩餘n-k+1個數的和
若t+Wk+W(k+1)<=M,則Xk=true,遞歸左兒子(X1,X2,..,X(k-1),1);否則剪枝;
若t+r-Wk>=M && t+W(k+1)<=M,則置Xk=0,遞歸右兒子(X1,X2,..,X(k-1),0);否則剪枝;
本題中W數組就是(1,2,..,n),所以直接用k代替WK值。

 

算法僞代碼:(這邊的s爲分析中的t,r爲上述分析中的r)



C++ 代碼實現

#include<iostream>
#include<cstdlib>
using namespace std;

void findSubSum(int m,int k,int st,int res,int *x)   //m表示爲和,st表示前k個元素,res表示剩下數的總和,x表示解向量     
{
    x[k]=1;
    if(m==st+k)
    {   
        for(int i=1;i<=k;i++)
        if(x[i]==1)
            cout<<i<<" ";
        cout<<endl;
    }   
    else if(st+k+k+1<=m)
        findSubSum(m,k+1,st+k,res,x);
        
    if((m<=st+res-k)&&(st+k+1<=m))
    {   
        x[k]=0;
        findSubSum(m,k+1,st,res-k,x);
    }   
}

void subSum(int m,int n)
{
    int *x=new int[n+1]();
    int sum=(n+1)*n/0.5;
    if(m<0||m>sum) 
    {   
        cout<<"bad num m:there is no result"<<endl;
        return;
    }   
        
    findSubSum(m,1,0,sum,x);
    free(x);
}
int main()
{
    int m,n;
    cout<<"please input the list number(N):"<<endl;
    cin>>n;
    cout<<"please input the sum number(M):"<<endl;
    cin>>m;
    subSum(m,n);
    return 0;
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章