http://www.lydsy.com/JudgeOnline/problem.php?id=1600
说好的今天开始刷水。。
本题一开始我以为是排列组合,但是自己弱想不出来,只想到了如果四边有一条边大于或等于第三边,那么这个四边形构造不出来。
即
a>=b+c+d时,不存在四边形
那么存在的情况就是a<b+c+d
得到
a<a+b+c+d
因为a<2a,a<b+c+d
所以a<(a+b+c+d)/2=n/2
那么我们就可以dp了。
只要找所有满足的边满足比长度的一半小就行了
设f[i, j]表示i块木板j长可以组成的四边形数
有f[i, j]=sum{ f[i-1, j-k] } 1<=k<=min(j, n/2-1)
k就代表了多出来的一边长为k
初始化f[0, 0]=1
#include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> using namespace std; #define rep(i, n) for(int i=0; i<(n); ++i) #define for1(i,a,n) for(int i=(a);i<=(n);++i) #define for2(i,a,n) for(int i=(a);i<(n);++i) #define for3(i,a,n) for(int i=(a);i>=(n);--i) #define for4(i,a,n) for(int i=(a);i>(n);--i) #define CC(i,a) memset(i,a,sizeof(i)) #define read(a) a=getint() #define print(a) printf("%d", a) #define dbg(x) cout << #x << " = " << x << endl #define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; } inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } inline const int max(const int &a, const int &b) { return a>b?a:b; } inline const int min(const int &a, const int &b) { return a<b?a:b; } int f[5][2505]; int main() { int n; read(n); int mid=(n+1)/2-1; f[0][0]=1; for1(i, 1, 4) for1(j, 1, n) for(int k=1; k<=min(j, mid); ++k) f[i][j]+=f[i-1][j-k]; print(f[4][n]); return 0; }