1. 程式人生 > >程式設計師互動聯盟(第一屆程式設計大賽第一題)

程式設計師互動聯盟(第一屆程式設計大賽第一題)

題目大意:

將1到N的連續整陣列成的集合劃分成兩個子集合,且保證每個集合的數字和是相等的。

例如,輸入N=3,對應的集合{1,2,3} 可以被劃分為{3},{1,2}兩個子集合,這兩個子集合中元素分別的和是相等的。輸入7,輸出4

思路:

首先1,2,3……N所有元素的和為 S= N*(N+1)/2, 如果S不能被2整除,那麼一定不能劃分,否則各個集合裡面的元素之和為 S = N*(N+1)/4,下面運用動態規劃的思想,令count[i] 表示 和為 i 的方案數目,那麼 count[j] = count[j] + count[j-i] , 表示和為 j 的方案數,等於原先的值 加上 和為 j-i 的方案數。 也就是說,沒有加 i 之前的方案數 現在加上i之後,和變為 j, 那麼和為j的方案數也應該加上 和為j-i的方案數,有點繞。。。

很經典的動態規劃的例子,剛開始做竟然沒想起來。

#include <iostream>
using namespace std;

#define N 40

int main(){
    int n,s;
    cin>>n;
    int count[400]; //該陣列count[i]表示和為i的方案數
    memset(count,0,sizeof(count));
    s = n*(n+1)/2;
    if(s%2!=0)
        cout<<0<<endl;
    s = s/2;
    count[0] = 1;
    for(int i=1;i<=n;i++){
        for(int j=s;j>=i;j--){
            count[j] += count[j-i];
        }
    }
    cout<<count[s]/2<<endl;
    return 0;
}