题意是将1到N的N个数分为两组,要求这两组数字和相等,问有多少种分法
第一遍暴力超时,后来在网上找了才知道是dp,然后这道题的dp方程和01背包有点像,dp[i][j]=dp[i-1][j]+dp[i-1][j-N];
方程的意思是在i个数字里选出总和为j的方案数,等于在i-1个数里,选出总和为j的方案数(没有i),加上在i-1个数里选出总和j-i的方案数(再加上后来的i,就等于j)。
因为返程和01背包很像,所以也能使用和01背包一样的方法优化空间
/* ID: modengd1 PROG: subset LANG: C++ */ #include <iostream> #include <stdio.h> #include <memory.h> #include <math.h> int N; long long dp[1000]; using namespace std; int main() { freopen("subset.in","r",stdin); freopen("subset.out","w",stdout); scanf("%d",&N); memset(dp,0,sizeof(dp)); long long sum=N*(N+1)/2; if(sum%2) cout<<0<<endl; else { dp[0]=1; sum/=2; for(int i=1;i<=N;i++) { for(int j=sum;j>=i;j--) dp[j]+=dp[j-i]; } cout<<dp[sum]/2<<endl; } return 0; }
时间: 2024-12-17 15:33:20