O(n ^ 2)中的子集和

时间:2015-12-21 18:49:39

标签: dynamic-programming subset subset-sum

我知道这个代码/逻辑对于解决子集求和问题是错误的,但似乎无法理解为什么。

计算所有可能子集的总和,并检查是否有任何等于所需的总和。这将在O(n ^ 2)中完成,这显然是错误的,因为我可以通过DP O(n * sum)来解决这个问题。

谢谢。

int main() {
    long long int t,n,i,j;
    scanf("%lld",&t);
    while(t--)
    {   
        long long int p[1005][1005],s[1005][1005]={0};
        long long int a[1005],sum;
        long long int counter=0;
        scanf("%lld %lld",&n,&sum);
        for(i=0;i<n;i++)
            scanf("%lld",&a[i]);
        s[0][0]=a[0];
        for(i=0;i<n;i++)
        {   
            for(j=i;j<n;j++)
            {
                if(i==j)
                {
                    s[i][j]=a[i];
                }
                else
                {
                    s[i][j]=a[j]+s[i][j-1];
                }
            }
        }
        int flag=0;
        for(i=0;i<n;i++)
        {
            for(j=i;j<n;j++)
            {
                if(s[i][j]==sum)
                    flag++;
            }
        }
        if(flag)
            cout<<1<<endl;
        else
            cout<<0<<endl;

    }
    return 0;
}  

2 个答案:

答案 0 :(得分:0)

您的代码的问题只是您没有计算所有子集的总和。这就是为什么你的代码看起来比实际需要的速度快得多。

请参阅https://en.wikipedia.org/wiki/Subset_sum_problem

答案 1 :(得分:0)

问题是s[i][j]只记录a[i]+a[i+1]+...+a[j]。实际上,您需要记录a[i...j]的所有子集的总和,其应为2^(j-i)。如果目标总和不是连续子集的总和,则代码应该很容易失败。