1. 程式人生 > >計蒜客 等和的分隔子集 DP

計蒜客 等和的分隔子集 DP

曉萌希望將1到N的連續整陣列成的集合劃分成兩個子集合,且保證每個集合的數字和是相等。例如,對於N=3,對應的集合{1,2,3}能被劃分成{3} 和 {1,2}兩個子集合.

這兩個子集合中元素分別的和是相等的。

對於N=3,我們只有一種劃分方法,而對於N=7時,我們將有4種劃分的方案。

輸入包括一行,僅一個整數,表示N的值(1≤N≤39)。

輸出包括一行,僅一個整數,曉萌可以劃分對應N的集合的方案的個數。當沒發劃分時,輸出0。

樣例輸入

7

樣例輸出

4

dp[i][j] 從1-i構成數字j的方式。

如果j=0/1,那麼dp[i][j]=1;只有一種方法

如果j<i,那麼dp[i][j]=dp[i-1][j]。因為j小於i那麼i不能用,所以等於以前的。

如果j>=i,那麼dp[i][j]=dp[i-1][j]+dp[i-1][j-i].從1-i構成j(不要i)以及1-(i-1)構成j-i的(要i)。

我們最後輸出1-n構成sum/2的。

之後除以二。因為兩張對稱的取法。



#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int n;
long long dp[100][1100];
int main()
{
    memset(dp,0,sizeof(dp));
    cin>>n;
    int zong=n*(n+1)/2;
    if(zong%2==1)
    {
        cout<<"0"<<endl;
        return 0;
    }
    for(int i=1;i<=n;i++)
    {
        int sum=i*(i+1)/2;
        for(int j=0;j<=sum;j++)
        {
            if(j==0||j==1)
                dp[i][j]=1;
            else if(j>=i)
            {
                dp[i][j]=dp[i-1][j]+dp[i-1][j-i];


            }
            else
            {  dp[i][j]=dp[i-1][j];


            }


        }
    }
    cout<<dp[n][zong/2]/2<<endl;
}