USCAO 2.2.2
来源:互联网 发布:js获取文件大小 编辑:程序博客网 时间:2024/06/10 06:30
那么仔细分析一下这个题是一个0/1背包的问题,将一个集合划分成 两个“元素总和相等”的集合,设原集合的元素总和为sum,则划分后的集合的元素综合都为sum/2。那么我们可以把sum/2看成背包的容量,原集合中的数字看为物品的重量及价值(这里价值维度可以淡化,就像装箱问题)。则原问题转化为 “从原集合中选出n个物品,使这n个物品恰好放满容量为sum/2的背包的方案总数”。
设分成的子集为set1,set2,sum=(n*(n+1)div 2)div 2。设num[i,j]表示取前i个数,使set1总数和为j的方案数.第i个数的值为i,根据是否取第i个数就有:
num[i,j]=num[i-1,j]+num[i-1,j-i] j-i>=0
num[i,j]=num[i-1,j] j-i<0
则最后的结果为num[n,sum] div 2。
【代码】:
//dp[i][j]表示 前 I个和为 J的可能有几种
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int n,sum;
long long num[40][780];
int main()
{
freopen("subset.in","r",stdin);
freopen("subset.out","w",stdout);
cin>>n;
if((n*(n+1)/2)%2)
{
cout<<"0"<<endl;
return 0;
}
sum=n*(n+1)/4;
memset(num,0,sizeof(num));
num[1][1]=1;
num[1][0]=1;
for(int i=2;i<=n;i++)
{
for(long j=0;j<=i*(i+1)/2;j++)
if(j>=i)
num[i][j]=num[i-1][j]+num[i-1][j-i];
else
num[i][j]=num[i-1][j];
}
cout<<num[n][sum]/2<<endl;
return 0;
}
- USCAO 2.2.2
- NKOI 1015(USCAO 2.2.2)子集
- USCAO 2.2.1
- USCAO 2.2.3
- USCAO 2.2.4
- USCAO 2.1.2
- USCAO 2.3.2
- USCAO 2.4.2
- USCAO 3.1.2
- USCAO 3.2.2
- USCAO-Section1.2 Transformations
- USCAO-Section1.2 Transformations
- USCAO section1.2 Palindromic Squares
- USCAO-Section1.2 Milking Cows
- USCAO 1.3.2 Barn Repair 修理牛棚
- USCAO section 2,2 Preface Numbering(算是DP吧)
- uscao--camelot
- USCAO 题解
- Vim的强大之处
- 数据结构的基本知识及常见试题
- 简明 Vim 练级攻略(转)
- POJ 1149
- USCAO 2.2.1
- USCAO 2.2.2
- Android模拟器输入中文问题
- USCAO 2.2.3
- Android开发 PK IOS开发
- 为什么Android机子运行时会卡而IPhone却不会?
- poj1061-扩展欧几里得算法
- USCAO 2.2.4
- POJ 1236
- USCAO 2.3.1