Bootstrap

基础背包问题

等和的分隔子集

晓萌希望将 1 到 N 的连续整数组成的集合划分成两个子集合,且保证每个集合的数字和是相等。例如,对于 N = 3,对应的集合 {1, 2, 3} 能被划分成 {3} 和{1, 2} 两个子集合。
这两个子集合中元素分别的和是相等的。
对于N=3,我们只有一种划分方法,而对于N=7 时,我们将有 4 种划分的方案。

输入格式
输入包括一行,仅一个整数,表示 N 的值 (1≤N≤39)。

输出格式
输出包括一行,仅一个整数,晓萌可以划分对应 N 的集合的方案的个数。当没发划分时,输出 0。

样例输入
7
样例输出
4
代码

#include<bits/stdc++.h>
using namespace std;
long long  dp[50][50005];
int n,ans;
int main() {
   
    cin>>n;
    int s=(1+n)*n/2;
    if(s & 1) {
   
        cout<<0<<endl;
        return 0;
    } 
    //s & 1表示s是否为奇数,如果是奇数就肯定不能一分为二,
    int ss=s/2;
    dp[0][0]=1;
    
    for(int i=1;i<ss;i++) {
   
        dp[0][i]=0;//当背包容量为i,前零个数的方案为1
    }
    for(int i=1;i<=n;i++) {
   
        for(int h=0;h<=ss;h++) {
   
            if(h<i) dp[i][h]=dp[i-1][h];//当h<i时,意味着背包需求为h,但是我i已经大于h了,意味着肯定不能把i放进背包,所以当前情况为上一种情况
            else {
   
                dp[i][h]=dp[i-1][h]+dp[i-1][h-i];
                //要么放进去要么不放进去
            }
        }
        
    }
    cout<<dp[n][ss]/2<<endl;//除以二是有重复的
    return 0;
}

其他代码求解

#include<bits/stdc++.h>
using namespace std;
long long  dp[2][50005];
int n,sum;
int main() {
   
    cin>>n;
    sum=n*(n+1)/2;
    dp[0][0]=1;
    if
;