算法实验8:划分问题

http://acm.sdibt.edu.cn/JudgeOnline/problem.php?id=4807

dp[i][j]表示前i个元素形成的集合的子集的和能否为j

如果dp[i-1,j] = 1或者dp[i-1,j-a[i]] = 1,则dp[i,j] =1.

每一行都是由他的前一行得到的

注意:dp[0][0] = 1;

 

 

 

 

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

int main() {
    int n,a[305],sum = 0,b[305];
    cin >> n;
    for(int i = 1; i <= n; i++) {
        cin >> a[i];
        sum += a[i];
    }
    if(sum %2 == 1) {
        cout << "no" << endl;
    } else {
    int** dp = (int**)malloc(sizeof(int*)*(n+1));
    for(int i = 0; i <= n; i++) {
        dp[i] = (int*)malloc(sizeof(int)*(sum/2+1));
    }
    for(int i = 0; i <= n; i++) {
        for(int j = 0; j <= sum/2; j++) {
             dp[i][j] = 0;
        }
    }
    dp[0][0] = 1;//一定要的啊
    for(int i = 1; i <= n; i++) {
        for(int j = 0; j <= sum/2; j++) {
            if(i == 1) {
                dp[1][0] = 1;
                dp[1][a[i]] = 1;
            } else {
                if(dp[i-1][j] == 1 || dp[i-1][j-a[i]] == 1)
                    dp[i][j] = 1;
            }
        }
    }
    if(dp[n][sum/2] == 1) {// 输出划分后的数组
        int k = n,t = sum/2,kk = 0;
        while(t != 0) {
            if(a[k] <= t && dp[k-1][t-a[k]]==1&&dp[k][t] == 1)
            {
            b[kk++] = a[k];
            t -= a[k];
            }
            k--;
        }
        for(int i = kk-1; i >= 0; i--) {
            cout << b[i];
            if(i > 0) cout << " ";
        }
        cout << endl;
    free(dp);
    }
    else
        cout << "no" << endl;
    }
    return 0;
}

 

posted on 2019-10-09 17:53  一只小毛球  阅读(371)  评论(0编辑  收藏  举报

导航