一种隐式的背包问题(与数字或集合相关)

一种隐式的01背包问题

例题:洛谷P1466[USACO2.2]集合 Subset Sums

题目描述

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

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

{ 1 , 6 , 7 } \{1,6,7\} {1,6,7} { 2 , 3 , 4 , 5 } \{2,3,4,5\} {2,3,4,5}
{ 2 , 5 , 7 } \{2,5,7\} {2,5,7} { 1 , 3 , 4 , 6 } \{1,3,4,6\} {1,3,4,6}
{ 3 , 4 , 7 } \{3,4,7\} {3,4,7} { 1 , 2 , 5 , 6 } \{1,2,5,6\} {1,2,5,6}
{ 1 , 2 , 4 , 7 } \{1,2,4,7\} {1,2,4,7} { 3 , 5 , 6 } \{3,5,6\} {3,5,6}

给出 n n n,你的程序应该输出划分方案总数。

提示

【数据范围】
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 39 1\le n \le 39 1n39

题目分析:

1.首先我们需要判断什么样的集合可以分成两等份。首先需要1~n的和为偶数,1–n的和我们可以使用高斯公式计算。sum = n*(n+1)/2;若sum为奇数则一定不可能分成两部分直接输出0.
2.若sum为偶数的话,一部分的和为sum/2.则原问题转化为从1~n中选出一部分数字,计算使这部分数字和为sum/2的种类数。
3.从题意中可知,每当选出一部分数和为sum/2的数字,其余剩下部分的和也为sum/2.则我们所求的答案为和为sum/2的数字的种类数除以2.
4.我们假设有X钟方式凑成J,同时Y-Z = J。(1<=Z<=n) .由此我们可以得出结论
dp[Y] =  sum(dp[Y-Z])(1<=Z<=n) 

又因为集合的无序性 { 1 , 2 } \{1,2\} {1,2} { 2 , 1 } \{2,1\} {2,1} 是同一种集合,为了避免出现这一类的重复计算我们可以以一个有序集合来表示所含元素相同的集合。

5.初始化条件dp[0] = 1,其含义为总和为0的集合有一种及空集。
6.我们注意到n是小于等于39的所以其时间复杂度不高,所以不用担心TLE为了避免int爆了,我们可以直接long long。(不开long long见祖宗)别问我为什么要写这一点,因为我开int炸了。

代码来咯!!!

#include<bits/stdc++.h>
using namespace std;
const int MAX = 8001;
long long dp[8001];

int main(){
	int n;
	printf("%d,"&n);
	int sum= (n+1)*n/2;
	memset(dp,0,sizeof(dp));
	dp[0] = 1;
	for(int i = 1;i<=n;++i){
		for(int j = sum;j>=i;--j){
			dp[j] += dp[j-i];
		}
	} 
	if(sum%2) scanf("0");
	else 
    cout << scanf("%ld",dp[sum/2]/2);
}
再送大伙两道题

洛谷P1566 加等式

洛谷P1806 跑步

最后祝:大伙写题大紫大红(不是)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值