BZOJ 1600: [Usaco2008 Oct]建造柵欄

1600: [Usaco2008 Oct]建造柵欄

Time Limit: 5 Sec  Memory Limit: 64 MB

Description

勤奮的Farmer John想要建造一個四面的柵欄來關住牛們。他有一塊長爲n(4<=n<=2500)的木板,他想把這塊本板切成4塊。這四塊小木板可以是任何一個長度只要Farmer John能夠把它們圍成一個合理的四邊形。他能夠切出多少種不同的合理方案。注意: *只要大木板的切割點不同就當成是不同的方案(像全排列那樣),不要擔心另外的特殊情況,go ahead。 *柵欄的面積要大於0. *輸出保證答案在longint範圍內。 *整塊木板都要用完。

Input

*第一行:一個數n

Output

*第一行:合理的方案總數

Sample Input

6

Sample Output

6


輸出詳解:

Farmer John能夠切出所有的情況爲: (1, 1, 1,3); (1, 1, 2, 2); (1, 1, 3, 1); (1, 2, 1, 2); (1, 2, 2, 1); (1, 3,1, 1);
(2, 1, 1, 2); (2, 1, 2, 1); (2, 2, 1, 1); or (3, 1, 1, 1).
下面四種 -- (1, 1, 1, 3), (1, 1, 3, 1), (1, 3, 1, 1), and (3,1, 1, 1) – 不能夠組成一個四邊形.

HINT

Source



好的,這是一題DP遞推。我一開始用了三位狀態+n^3的遞推,果斷TLE了,我真是作死!實際上只要保證任意一條邊小於總長度的一半就可以了,我偷了個懶,算了全部的結果,結果死的爽爽的!以後做題不能這麼隨意了。所以應該是二維的遞推f[i][j]表示i塊木板拼了j個長度的方案數,並時刻保證任意一條邊小於總長度的一般就可以了。

代碼:

/*Author:WNJXYK*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
using namespace std;

#define LL long long

inline void swap(int &x,int &y){int tmp=x;x=y;y=tmp;}
inline void swap(LL &x,LL &y){LL tmp=x;x=y;y=tmp;}
inline int remin(int a,int b){if (a<b) return a;return b;}
inline int remax(int a,int b){if (a>b) return a;return b;}
inline LL remin(LL a,LL b){if (a<b) return a;return b;}
inline LL remax(LL a,LL b){if (a>b) return a;return b;}

int n,mx;
int f[5][2505];
int main()
{
	f[0][0]=1;
	scanf("%d",&n);
	int mx=(n+1)/2-1;
	for(int i=1;i<=4;i++)
	    for(int j=1;j<=n;j++)
		    for(int k=1;k<=remin(mx,j);k++)
			    f[i][j]+=f[i-1][j-k];
    printf("%d\n",f[4][n]);
	return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章