子集和問題--對代碼進行刪減

子集和問題
Time Limit: 1000 ms Memory Limit: 65536 KiB

Problem Description
子集和問題的一個實例爲〈S,t〉。其中,S={ x1 , x2 ,…,xn }是一個正整數的集合,c是一個正整數。子集和問題判定是否存在S的一個子集S1,使得:

試設計一個解子集和問題的回溯法。
對於給定的正整數的集合S={ x1 , x2 ,…,xn }和正整數c,計算S 的一個子集S1,使得:

Input
輸入數據的第1 行有2 個正整數n 和c(n≤10000,c≤10000000),n 表示S 的大小,c是子集和的目標值。接下來的1 行中,有n個正整數,表示集合S中的元素。
Output
將子集和問題的解輸出。當問題無解時,輸出“No Solution!”。

Sample Input

5 10
2 2 6 5 4

Sample Output
2 2 6

幫助自己理解,跑一邊例題,可能我太笨啦,個人理解,不確定對哈
輸入之後,進行sum是否小於C的判讀。flag = 0,接下來dfs(0),進入dfs函數
dfs(0):if循環,v[0] = 0且c - a[0] >= 0;c = c - a[i] = 10 - 2 = 8;
v[0]被標記,ans[0] = 2存入。
else dfs(1),類似,c = 8 - 2 = 6;v[1]標記,ans[1] = 2記錄下來,
繼續else dfs(3),c = 6 - 6 = 0;v[2]標記,ans[2] = 6記錄,c == 0滿足,
有因爲flag = 0,直接輸出print(2);flag = 0,return;結束。
介於此處並沒有體現出回溯這一步,那我們就換個例子,2 2 9 6 5,再來一次
2 2 一樣,直接到9,c = 6 - 9 < 0,進不去循環,還是例子不對,2 2 5 6 2試試,c = 6 - 5 = 1,下一步dfs(3),c - 6 和c - 2都小於0,所以,回到dfs(2)......後續更新哈哈,先不想了

接下來看代碼,我在測試過程中發現很多的代碼是無用的,所以對代碼進行刪減,刪減和備註的代碼在下面

#include<bits/stdc++.h>

using namespace std;

int v[101000];
int a[1000001],ans[1000001];
int c, n, flag;

void print(int x)
{
    for(int i = 0; i <= x; i++)///注意i <= x;
        cout<<ans[i]<<" ";
    cout<<endl;
}

void dfs(int x)
{
    for(int i = 0; i < n; i++)
    {
        if(v[i] == 0 && c - a[i] >= 0)
        {
            c = c - a[i];
            v[i] = 1;
            ans[x] = a[i];
            if(c == 0)
            {
                if(flag == 0)///判斷
                    print(x);
                flag = 1;
                return;
            }
            else
                dfs(x + 1);
            v[i] = 0;
            c += a[i];
        }
    }
}
int main()
{
    while(cin>>n>>c)
    {
        int sum = 0;
        for(int i = 0; i < n; i++)
        {
            cin>>a[i];
            sum += a[i];
        }
        if(sum < c)
        {
            cout<<"No Solution!"<<endl;///輸出被弄錯了
            break;
        }
        memset(v, 0, sizeof(v));
        memset(ans, 0, sizeof(ans));
        flag = 0;
        dfs(0);
        if(flag == 0)
            cout<<"No Solution!"<<endl;
    }
}
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>

using namespace std;

int a[10000];///輸入數組
int v[10000];///標記訪問
int ans[10000];///ans是記錄數組
int c, n, flag;

void print(int x)
{
    for(int i = 0; i <= x; i++)
        cout<<ans[i]<<" ";
    cout<<endl;
    ///return;
}

void dfs(int x)
{
    ///if(flag == 1) return;
    for(int i = 0; i < n; i++)
    {
        if(v[i] == 0 && c - a[i] >= 0)
        {
            ///if(flag == 1) return;
            c -= a[i];///用c減去每個數,其實就是幾個數之和等於c
            v[i] = 1;
            ans[x] = a[i];///ans是記錄數組
            if(c == 0)///如果找到一組解,直接輸出,完成任務
            {
                if(flag == 0)
                    print(x);
                flag = 1;
                return;
            }
            else
                dfs(x + 1);
            if(flag == 1) return;
            v[i] = 0;///回溯一步
            c += a[i];
        }
    }
}

int main()
{
    while(cin>>n>>c)
    {
        int sum = 0;
        for(int i = 0; i < n; i++)
        {
            cin>>a[i];
            sum += a[i];
        }
        if(sum < c)///如果所有的數加起來都小於c,那麼不可能有解
        {
            cout<<"No Solution!"<<endl;
            break;
        }
        memset(v, 0, sizeof(v));
        memset(ans, 0, sizeof(ans));
        flag = 0;
        dfs(0);
        if(flag == 0)
            cout<<"No Solution!"<<endl;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章