通过子集dp问题获取分段错误

时间:2019-02-18 12:20:44

标签: subset dynamic-programming

给出一组数字,检查是否可以将其划分为两个子集,以使两个子集中的元素之和相同或不同 我在C ++(g ++ 5.4)中遇到了此问题的分段错误。 这是我用C ++提交解决方案的地方

https://practice.geeksforgeeks.org/problems/subset-sum-problem/0

我正在检查数组是否可以分为两个相等的部分。所以我只是在检查是否存在一个总和等于数组总和一半的子集

我已经通过动态编程实现了以下逻辑

让dp [i] [j]表示是或否,是否可以使用范围为[0,i](均包括在内)的元素构成总和为j的子集,其中i是基于0的索引。对于这个传统问题,我没有做任何新的事情。但是我遇到了细分错误。该程序为小型测试用例提供正确的输出。我犯了什么错误

我没有使用任何评论,因为我没有做任何新的事情。希望这是可以理解的。

#include <iostream>
#include <bits/stdc++.h>
#include<cstdio>
#define ll long long int
using namespace std;


bool isVowel(char c){
    return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}

bool isLower(char c){
    return 97 <= c && c <= 122;
}


int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cout << setprecision(10);

    ll t, n;
    cin >> t;
    while (t--) {
        cin >> n;
        ll a[n];
        ll sum = 0;

        for (ll i = 0; i < n; i++) {
            cin >> a[i];
            sum += a[i];
        }

        if (sum % 2) {
            cout << "NO" << '\n';
            continue;
        }

        sum /= 2;
        ll dp[n][sum + 1];
        for (ll i = 0; i < n; i++) {
            for(ll j = 0; j < sum + 1; j++) {
                dp[i][j] = 0;
            }
        }

        for (ll i = 0; i < n; i++) {
            dp[i][a[i]] = 1;
            dp[i][0] = 1;
        }


        for (ll i = 1; i < n; i++) {
            for (ll j = 1; j < sum + 1; j++){
                if (j - a[i] > 0) {
                    dp[i][j] = dp[i - 1][j - a[i]];
                }

                dp[i][j] |= dp[i - 1][j];
            }
        }

        cout << (dp[n - 1][sum] ? "YES" : "NO") << '\n';

    }
}

1 个答案:

答案 0 :(得分:1)

细分错误是由于

ll dp[n][sum + 1];

尽管约束条件说 1 <= N <= 100,0 <= arr [i] <= 1000 ,但使用的测试用例可能要大得多,因此 ll dp [ n] [sum + 1] 会占用大量的堆栈内存,请使用

bool dp[n][sum + 1];

应该工作正常。

另一方面,请避免随机使用ll,请根据约束条件使用它们。