【问题标题】:How to find size of largest subset of a sub-sequence equal to a sum如何找到等于总和的子序列的最大子集的大小
【发布时间】:2018-08-10 09:10:21
【问题描述】:

我有来自hackerearth的this问题

给定一个包含 N 个整数、C 个卡片和 S 个总和的数组。每张卡都可以使用 将给定数组中的整数递增或递减 1。 查找是否有任何子集(在使用任何数量的卡片之后/之前) 在给定的数组中求和 S。

输入格式

输入的第一行包含一个整数 T,表示编号。的 测试用例。每个测试用例有 2 行输入。每个的第一行 测试用例有三个整数 N(数组大小)、S(子集总和)和 C(卡数)。每个测试用例的第二行有 N 个整数 数组(a1 到 aN),以空格分隔。

约束

1 1 1 0 1

输出格式

如果存在具有给定总和的子集,则打印 TRUE,否则打印 FALSE。

所以这基本上是子集和问题的一种变体,但是我们不需要找出具有和 S 的给定子集是否存在,我们需要找到从序列 indexN-1 的最大子集s 的值并将它的长度与我们的 C 值进行比较,看看它是否更大。如果是,那么我们有足够的元素来使用我们的C 卡片修改总和,然后我们打印出我们的答案。这是我的代码

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int N, S, C;


int checkSum(int index, int s, vector<int>& a, vector< vector<int> >& dP) {

    if (dP[index][s] != -1)
        return dP[index][s];

    int maxNums = 0;    // size of maximum subset array

    for (int i = index; i < N; i++) {

        int newSum = s - a[i];
        int l = 0;

        if (newSum == 0) {
            l = 1;
        } if (newSum > 0) {

            if (i < (N-1)) {    // only if we can still fill up sum
                l = checkSum(i + 1, newSum, a, dP);

                if (l > 0)      // if it is possible to create this sum
                    l++;        // include l in it
            } else {
                // l stays at 0 for there is no subset that can create this sum
            }

        } else {
            // there is no way to create this sum, including this number, so skip it;
            if (i == (N-1))
                break;      // don't go to the next level

            // and l stays at 0
        }

        if (l > maxNums) {
            maxNums = l;
        }
    }

    dP[index][s] = maxNums;
    return maxNums;
}


int main() {

    int t;
    cin >> t;

    while (t--) {
        cin >> N >> S >> C;
        vector<int> a(N);

        for (int i = 0; i < N; i++)
            cin >> a[i];

        vector< vector<int> > dP(N, vector<int>(S + C + 2, -1));

        bool possible = false;

        for (int i = 0; i <= C; i++) {
            int l = checkSum(0, S-i, a, dP);
            int m = checkSum(0, S+i, a, dP);

            if ( (l > 0 && l >= i) || (m > 0 && m >= i) ) {

                cout << "TRUE" << endl;
                possible = true;
                break;
            }

        }

        if (!possible)
            cout << "FALSE" << endl;
    }

    return 0;
}

所以基本上,0 意味着不可能从元素索引到 N-1 创建一个等于 s 的子集,而 -1 意味着我们还没有计算它。任何其他值表示总和为 s 的最大子集的大小。此代码未通过所有测试用例。怎么了?

【问题讨论】:

    标签: c++ algorithm c++11 c++14


    【解决方案1】:

    您在下一行错过了else

    } if (newSum > 0) {
    

    这会使您的程序在某些情况下在通过l 更新maxNums 之前出现意外的提前中断。

    例如,N=1、S=5、C=0、a={5}


    潜在的逻辑问题

    您已限制编号。要使用的卡片数量不超过子集大小,而问题从未说明您不能将多张卡片应用于相同的整数。

    我的意思是 l &gt;= im &gt;= i

    if ( (l > 0 && l >= i) || (m > 0 && m >= i) ) {
    

    【讨论】:

      【解决方案2】:

      看来你有逻辑缺陷。

      您需要找到最短的子集(总和在S-C..S+C 范围内)并将其大小与C 进行比较。如果子集较短,则可以进行所需的总和。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-04
        • 2013-08-06
        • 2019-09-26
        • 1970-01-01
        • 1970-01-01
        • 2022-10-12
        • 2021-01-08
        • 2017-01-10
        相关资源
        最近更新 更多