分类:DP,递推,记忆化搜索

作者:ACShiryu

时间:2011-7-15

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

题目大意就是求讲数据1…N分成两组,使得两组中元素的和加起来相等,求这样分组的情况数

可以利用递推的方法求该题的解,注意:f(k,a)=(f(k-1,a+k)+f(k-1,a-k))/2;其中f(k,a)表示讲1…k元素分两组,使第一组比第二组多a;

因为k只可能分到第一组或第二组这两种情况,如果k加到第一组后使得第一组比第二组多a,则要原来的分组中第一组比第二组多a-k

同理如果k加到第二组后使得第一组比第二组多a,则要原来的分组中第一组比第二组多a+k。

因为交换两组元素后也满足条件,而只算一个解,故后面要除2;

很显然题目要求的是f(N,0);

为节省递推时间,可使用记忆化搜索,考虑到数据不大,又a有正负之分,可加数组适当开大。

数据分析:N最大为39,32位整数可能存不下,故要使用64位扩展,故要将数据声明为long long .因为使用的是记忆化搜索,很大程度上减少了重复搜索的情况,时间复杂度为O(n^3),远优于O(2^n),不会超时.。

参考代码:

1 /*  2 ID:shiryuw1  3 PROG:subset  4 LANG:G++ //64位整数要用long long 5 */ 6 #include<iostream> 7 #include<cstdlib> 8 #include<cstdio> 9 #include<cstring> 10 #include<algorithm> 11 #include<cmath> 12 using namespace std; 13 int sum=0; 14 int n; 15 long long fid[40][2000]; //是否寻找过dp(k,a+1000),当为-1时为否16 long long dp(int k,int a) 17 { 18     if(k==0) 19     { //当为0时不合要求,故返回020         return 0; 21     } 22     if(k==1) 23     { //当为1是可知只有可能两边的集合相差只能为1或-124         if(abs(a)==1) 25             return 1; 当相差为1或-1时,则有一种情况符合26         return 0; 27     } 28     if(k==2) 29     { //理由同k=1时30         if(abs(a)==1||abs(a)==3) 31             return 1; 32         return 0; 33     } 34     if(fid[k][a+1000]==-1) //如果k,a没有访问过,则访问,并将访问结果存在该数组中,很明显该数组的结果不会再是-1否则直接返回fid[k][a+1000],避免重复搜索。35         fid[k][a+1000]=dp(k-1,a+k)+dp(k-1,a-k); 36     return fid[k][a+1000]; 37 }38 39 int main() 40 { 41     freopen("subset.in","r",stdin); 42     freopen("subset.out","w",stdout); 43     cin>>n; 44     memset(fid,-1,sizeof(fid)); //初始化fid数组为-145     printf("%lld\n",dp(n,0)/2); 寻找把1……N分成两组后使两组相差0的情况数46     return 0; 47 } 

  

转载于:https://www.cnblogs.com/ACShiryu/archive/2011/07/15/2107785.html

USACO 2.2.2 Subset Sums解题报告相关推荐

  1. USACO 3.3.2 Shopping Offers解题报告

    写在前面:因为之前没写的C++的USACO Training的解题报告太多--所以就不写了,要是想要代码可以联系我:xiedong_1993@foxmail.com 这题就是传说中的五维背包,其实写起 ...

  2. USACO Section 1.5 Prime Palindromes 解题报告

    题目 题目描述 题目就是给定一个区间[a,b]((5 <= a < b <= 100,000,000)),我们需要找到这个区间内所有既是回文串又是素数的数字. 输入样例 5 500 ...

  3. usaco 2.1.4 Subset Sums 【母函数】

    (1+x)*(1+x^2)*(1+x^3)*--*x^n   则 x^(n*(n+1)/2) 的系数一半为ans /*ID: w.x.f.g1PROG: subsetLANG: C++ */#incl ...

  4. USACO Section2.1 Hamming Codes 解题报告 【icedream61】

    hamming解题报告 ---------------------------------------------------------------------------------------- ...

  5. USACO Section2.2 Preface Numbering 解题报告 【icedream61】

    preface解题报告 ---------------------------------------------------------------------------------------- ...

  6. usaco ★Subset Sums 集合

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

  7. USACO Section1.3 Combination Lock 解题报告

    combo解题报告 -- icedream61 博客园(转载请注明出处) --------------------------------------------------------------- ...

  8. USACO Section1.5 Superprime Rib 解题报告

    sprime解题报告 -- icedream61 博客园(转载请注明出处) -------------------------------------------------------------- ...

  9. USACO Training Section 1.3 Calf Flac 解题报告AC代码

    解题报告: 主要方法是生长法,考虑每一位的左右各有多长的回文串,输出最长的那个,比较好想--不过要注意区分字串的奇偶. 其他实现细节看代码里的注释吧-- AC代码: /* ID: yuanmz91 P ...

最新文章

  1. Apache Flink 漫谈系列(12) - Time Interval(Time-windowed) JOIN...
  2. Unable to get repr for<class‘torch.Tensor‘>
  3. php的$_SERVER['HOSTNAME']
  4. 3.2 目标点检测-深度学习第四课《卷积神经网络》-Stanford吴恩达教授
  5. mysql主从复制思考_Mysql主从复制(拓展博客文章分享及思考)
  6. 【Linux】Linux中vim的使用
  7. Ajax — 大事件项目(第二天)
  8. 【译】XNA Shader 程序设计(二)
  9. mongodb备份还原
  10. BZOJ 3282 Link Cut Tree (LCT)
  11. Python-Pandas
  12. MATLAB中的线性插值
  13. html字体加粗代码_9102年了,公众号还不会换字体?
  14. 28335之GPIO输入
  15. 深度解读,北斗与综合PNT体系
  16. 随机无梯度Frank-Wolfe方法的统一分析
  17. 用KOPPT,大家的姿势对了没?
  18. 查看Win10激活剩余时间
  19. CSS第四篇(复合选择器)
  20. 一件登录facebook_Facebook抵制抵制是防火的,那是一件好事

热门文章

  1. python全栈脱产第25天------组合、多态、封装、property装饰器
  2. 微信小程序 --- 图片自适应、本地图片的使用
  3. 在windows环境下基于sublime text3的node.js开发环境搭建
  4. 2015-03-06——正则表达式基础
  5. JAVA GUI关闭按钮不起作用(用SwingWorker解决)
  6. linux df命令参数详解
  7. recycleView 滑动删除Item,拖拽切换Item,你想了解的都在这儿
  8. Observable.OnSubscribe 的理解
  9. Echarts 动态获取数据进行图表的展示
  10. NodeJs初学者经典入门解析