USACO 2.2 Subset Sums(subset)

        這個題是經典0-1揹包問題的變形,在正整數區間[1,n]內,選擇一個子集,和爲n*(n+1)/4,求總共能夠選擇的子集數除以2。首先想到的是窮舉可能的狀況,可是始終超時。後來採用動態規劃,用ans[i][j]表示在區間[0,i]選擇一個其和爲j的子集,總共可能的子集數,因而狀態轉移方程:ios

   if(j<i)    ans[i][j]=ans[i-1][j];
   if(j==i)  ans[i][j]=ans[i-1][j]+1;
   if(j>i)    ans[i][j]=ans[i-1][j]+ans[i-1][j-i]; spa

其中起始點a[1][1]=1,i取值範圍:1~n,j取值範圍:1~n*(n+1)/4。code

 

/*
ID:jzzlee1
PROG:subset
LANG:C++
Dear double_tings:
i love you.
*/
//#include<iostream>
#include<fstream>
#include<cmath>
#include<string>
#include<cstring>
#include<bitset>
using namespace std;
ifstream cin("subset.in");
ofstream cout("subset.out");
long long ans[40][40*(40+1)/2]; 
int main(){
	int n;
	cin>>n;
	int half=n*(n+1)/4;
	if(n*(n+1)%4!=0) 
	{
		cout<<0<<endl; 
		return 0;
	}
	ans[1][1] = 1;
	for(int i = 2; i <= n; i++)
		for(int j = 1; j <= half; j++)
			if(j < i)	ans[i][j] = ans[i-1][j];
			else if(j == i) ans[i][j] = ans[i-1][j]+1;
			else  ans[i][j] = ans[i-1][j] + ans[i-1][j-i]; 
    cout<<ans[n][half]/2<<endl;  
	return 0;
}
相關文章
相關標籤/搜索