USACO: Subsets (Inefficient)

一个人想着一个人 提交于 2019-12-13 09:19:26

问题


I am trying to solve subsets from the USACO training gateway...

Problem Statement

For many sets of consecutive integers from 1 through N (1 <= N <= 39), one can partition the set into two sets whose sums are identical.

For example, if N=3, one can partition the set {1, 2, 3} in one way so that the sums of both subsets are identical:

{3} and {1,2} This counts as a single partitioning (i.e., reversing the order counts as the same partitioning and thus does not increase the count of partitions).

If N=7, there are four ways to partition the set {1, 2, 3, ... 7} so that each partition has the same sum:

{1,6,7} and {2,3,4,5} {2,5,7} and {1,3,4,6} {3,4,7} and {1,2,5,6} {1,2,4,7} and {3,5,6} Given N, your program should print the number of ways a set containing the integers from 1 through N can be partitioned into two sets whose sums are identical. Print 0 if there are no such ways.

Your program must calculate the answer, not look it up from a table.

End

Before I was running on a O(N*2^N) by simply permuting through the set and finding the sums.

Finding out how horribly inefficient that was, I moved on to mapping the sum sequences... http://en.wikipedia.org/wiki/Composition_(number_theory)

After many coding problems to scrape out repetitions, still too slow, so I am back to square one :(.

Now that I look more closely at the problem, it looks like I should try to find a way to not find the sums, but actually go directly to the number of sums via some kind of formula.

If anyone can give me pointers on how to solve this problem, I'm all ears. I program in java, C++ and python.


回答1:


Actually, there is a better and simpler solution. You should use Dynamic Programming instead. In your code, you would have an array of integers (whose size is the sum), where each value at index i represents the number of ways to possibly partition the numbers so that one of the partitions has a sum of i. Here is what your code could look like in C++:

int values[N];
int dp[sum+1]; //sum is the sum of the consecutive integers

int solve(){
    if(sum%2==1)
        return 0;
    dp[0]=1;
    for(int i=0; i<N; i++){
        int val = values[i]; //values contains the consecutive integers
        for(int j=sum-val; j>=0; j--){
            dp[j+val]+=dp[j];
        }
    }
    return dp[sum/2]/2;
}

This gives you an O(N^3) solution, which is by far fast enough for this problem.

I haven't tested this code, so there might be a syntax error or something, but you get the point. Let me know if you have any more questions.




回答2:


This is the same thing as finding the coefficient x^0 term in the polynomial (x^1+1/x)(x^2+1/x^2)...(x^n+1/x^n), which should take about an upper bound of O(n^3).



来源:https://stackoverflow.com/questions/6447959/usaco-subsets-inefficient

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!