USACO: Subsets (Inefficient)

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.

Answers


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.


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).


Need Your Help

Fast searching for the lowest value greater than x in a sorted vector

matlab optimization

Fast means better than O(N), which is as good as find() is capable of. I know there is ismembc and ismembc2, but I don't think either of them are what I am looking for. I read the documentation and...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.