【题解】洛谷P1466[USACO2.2]集合Subset Sums(0/1背包详解)

题目

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

题解

此题关键在于将“能划分成几种子集”转化为“有多少子集的和是全集和的一半”。由于和不大,所以可以考虑递推。这个问题的模型是“0/1背包问题”:从一些物品中选取一部分,装满背包。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000;
int n,sum;
ll f[maxn][40];	//f[i][j]表示1~j的子集中元素和为i的集合的数量 
inline void solve()
{
	for(int i=0;i<=n;i++) f[0][i]=1;	//空集 
	for(int i=1;i<=sum/2;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i-j>=0) f[i][j]=f[i-j][j-1]+f[i][j-1];	//1~j的子集分为含j的和不含j的 
			else f[i][j]=f[i][j-1];		//只能不含j 
		}
	}	 
	printf("%lld\n",f[sum/2][n]/2);	//注意答案要除以2,因为两个子集组合成一个全集
}

int main()
{
	scanf("%d",&n);
	sum=(1+n)*n/2;
	if(sum&1) {printf("0\n"); return 0;}	//sum为奇数时,无法分成相等两部分
	solve(); 
	
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值