zoukankan      html  css  js  c++  java
  • USACO 2.2 Subset Sums 集合(subset)

    Description

    对于从1到N的连续整集合,能划分成两个子集合,且保证每个集合的数字和是相等的。
    举个例子,如果N=3,对于{1,2,3}能划分成两个子集合,他们每个的所有数字和是相等的:

    • {3} and {1,2}

    这是唯一一种分法(交换集合位置被认为是同一种划分方案,因此不会增加划分方案总数)
    如果N=7,有四种方法能划分集合{1,2,3,4,5,6,7},每一种分发的子集合各数字和是相等的:

    • {1,6,7} and {2,3,4,5} {注 1+6+7=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}

    给出N,你的程序应该输出划分方案总数,如果不存在这样的划分方案,则输出0。程序不能预存结果直接输出。


      好  废话不多说这是我在Ubuntu下打的第一个代码,个人认为Ubuntu下很多界面较好  风格也还行(又说废话了)。。。

      这道题是一个dp  大致的意思是从1-n的每个数都给你一个  然后叫你找有多少种可能a+b+c...==x+y+z(当然a,b,c,x,y,都属于这n个数)同时  这些数都要用完而且不能重复用   

      刚刚看题目颇为不解  这用dp该怎么做  明显是坑爹嘛  后来实在想不出来就去baidu了(。。。)  然后看到一种普遍的解法就是看作一个01背包然后“

    如果M=n*(n+1)/2是奇数,则没有分法。如果是偶数,背包容量为M/2,dp[k] += dp[k-i],(i=1,2,...,n)计算k的时候为避免重算,

    需倒着进行。”(这不还是看不懂嘛(请原谅我的愚笨))

      再后来一想[1,n]这个区间里所有数不久形成了一个an=n的等差数列嘛   那么根据求和公式sn=n+n*(n-1)/2 =n*(n+1)/2  既然这样 要使两边相等 那么

    l(左边的和)=r(右边的和)=n*(n+1)/4  这样的话如果算出来的n*(n+1)/4为小数的话那么肯定就不可能有解了嘛  所以只要在开始判断一下n*(n+1)/4能不能除尽(即判断n*(n+1)%4是否为0)  然后如果除不尽就直接return 掉就行了。

      在初步的判断完以后  我们就要开始用dp大法了   可以看作有n个物品  给你n*(n+1)/4的质量   这一次的分法就等于这一次j比i多出来的数的分法加上原来i的分法       


      代码如下:

     1 #include<iostream>
     2 using namespace std;
     3 const int maxn=10000+10;
     4 long long f[100000];
     5 int n,s;
     6 int main()
     7 {
     8     cin>>n;
     9     s=n*(n+1);
    10     if(s%4!=0)
    11     {
    12         cout<<0<<endl;
    13         return 0;
    14     }
    15     s/=4;
    16     f[0]=1;
    17     for(int i=1;i<=n;i++)
    18         for(int j=s;j>=i;j--)
    19             f[j]+=f[j-i];
    20     cout<<f[s]/2<<endl;
    21     return 0;
    22 }
  • 相关阅读:
    WebService学习--(一)webservice相关概念
    根据日期推断某天某周某日
    Eclipse快捷键
    Java IO学习--(五)字节和字符数组
    Java IO学习--(四)网络
    Java IO学习--(三)通道
    Java IO学习--(二)文件
    Java IO学习--(一)概述
    JVM学习--(八)java堆分析
    Linux加密、安全版块、root密码破解
  • 原文地址:https://www.cnblogs.com/luowenqing/p/4392321.html
Copyright © 2011-2022 走看看