• USACO2.2.2Subset Sums


    Subset Sums
    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
    题解:看完题目果断想到了搜索,因为这个题目本质上和Healthy Holsteins是一样的。都是求集合的子集问题。对于每个元素都有两种选择,即选或者不选,这样的话用搜索是非常优美的。所以果断写了个DFS。
    这是代码:
     1 #include<stdio.h>
     2 long maxlen,count,total,n;
     3 void dfs(long step)
     4 {
     5   if(count<0) return;
     6   if(step>n)
     7   {
     8 
     9     if(count==0) total++;
    10     return;
    11 }
    12     count-=step;
    13     dfs(step+1);
    14     count+=step;
    15     dfs(step+1);
    16 }
    17 int main(void)
    18 {
    19     freopen("subset.in","r",stdin);
    20     freopen("subset.out","w",stdout);
    21     scanf("%ld",&n);
    22     total=0;
    23     if((n*(n+1)%4)!=0)
    24     {
    25         printf("0\n");
    26         return 0;
    27     }
    28     else
    29    {
    30         count=n*(n+1)/4;
    31         dfs(1);
    32    }
    33     printf("%ld\n",total/2);
    34     return 0;
    35 }
    
    
    不过在USACO上提交之后,第四个点N=31直接超时了。突然才想到N=39时,搜索量是多么的恐怖!!!2^39=549755813888。。。。然后继续想,因为对于每个数来说,就两种状态嘛,选或者不选,突然联想到0-1背包,因为它对于第K个物品,要么选,要么不选。只是0-1背包求的是最大价值方案。而此题是从N个元素中选取K个元素,使得背包装满的方案数。所以两者还是有点区别的,但思想是一样的。不过当时直接是套01背包的公式,所以果断WA了。。。需要对01背包稍微修改一下才行。。
    状态转移方程为:
    f[i][j]=f[i-1][j]+f[i-1][j-i],j>=i;
    f[i][j]=f[i-1][j],j<i;
    View Code
     1 /*
     2 ID:spcjv51
     3 PROG:subset
     4 LANG:C
     5 */
     6 #include<stdio.h>
     7 int main(void)
     8 {
     9     freopen("subset.in","r",stdin);
    10     freopen("subset.out","w",stdout);
    11     int n,i,j,count;
    12     long long f[40][1000];
    13     scanf("%d",&n);
    14     if((n*(n+1)%4)!=0)
    15     {
    16         printf("0\n");
    17         return 0;
    18     }
    19     count=n*(n+1)/4;
    20     memset(f,0,sizeof(f));
    21     f[1][0]=1;
    22     f[1][1]=1;
    23     for(i=2; i<=n; i++)
    24         for(j=count; j>=0; j--)
    25         if(j>=i)
    26            f[i][j]=f[i-1][j]+f[i-1][j-i];
    27         else
    28           f[i][j]=f[i-1][j];
    29     printf("%lld\n",f[n][count]/2);
    30     return 0;
    31 }
     


  • 相关阅读:
    hdu1074Doing Homework
    1088滑雪
    hdu1078FatMouse and Cheese
    hdu1058Humble Numbers
    hdu1114 Piggy-Bank
    hdu1069Monkey and Banana
    未解决的问题_c#中,最小化触发事件
    WPF Button 样式资源设置&后台生成button样式
    .NET 调用外部exe程序,出现已停止工作
    json类序列化与反序列化参考
  • 原文地址:https://www.cnblogs.com/zjbztianya/p/2893416.html
Copyright © 2020-2023  润新知