USACO Section 2.2 Subset Sums(整数划分01背包思想)
JRM
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.
PROGRAM NAME: subset
INPUT FORMAT
The input file contains a single line with a single integer representing N, as above.
SAMPLE INPUT (file subset.in)
7
OUTPUT FORMAT
The output file contains a single line with a single integer that tells how many same-sum partitions can be made from the set {1, 2, ..., N}. The output file should contain 0 if there are no ways to make a same-sum partition.
SAMPLE OUTPUT (file subset.out)
4
题意:输入一个 n ,从 1 到 n 这 n 个数分成两部分,这两部分的和相等,问这种方法有多少种。
分析:d[i][j] 表示前 i 个数组合起来的和是 j 的种数,对 j 考虑选择与不选择两种情况,不选:d[i-1][j],选择:d[i-1][j-i];所以d[i][j]=d[i-1][j]+d[i-1][j-i];
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 ID: dizzy_l1 3 LANG: C++ 4 TASK: subset 5 */ 6 #include<iostream> 7 #include<cstring> 8 #include<cstdio> 9 10 using namespace std; 11 12 long long d[1000]; 13 14 int main() 15 { 16 freopen("subset.in","r",stdin); 17 freopen("subset.out","w",stdout); 18 int n,sumv,i,j; 19 while(cin>>n) 20 { 21 sumv=(n+1)*n/2; 22 if(sumv%2==1) 23 { 24 printf("0\n"); 25 continue; 26 } 27 sumv=sumv/2; 28 memset(d,0,sizeof(d)); 29 d[0]=1; 30 for(i=1;i<=n;i++) 31 { 32 for(j=sumv;j>=i;j--) 33 { 34 d[j]+=d[j-i]; 35 } 36 } 37 cout<<d[sumv]/2<<endl; 38 } 39 return 0; 40 }