【题解】洛谷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;
}

猜你喜欢

转载自blog.csdn.net/zjgmartin/article/details/108415837
今日推荐