http://codeforces.com/problemset/problem/437/E
题意:求一个多边形划分成三角形的方案数
思路:区间dp,每次转移只从一个方向转移(L,R连线的某一侧),能保证正确。
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<iostream> #define ll long long const ll Mod=1000000007; ll f[5005][5005]; struct Point{ double x,y; Point(){} Point(double x0,double y0):x(x0),y(y0){} }p[500005]; Point operator -(Point p1,Point p2){ return Point(p1.x-p2.x,p1.y-p2.y); } double operator *(Point p1,Point p2){ return p1.x*p2.y-p1.y*p2.x; } int read(){ int t=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} return t*f; } ll solve(int l,int r){ if (f[l][r]!=-1) return f[l][r]; if (l>r) return f[l][r]=0; if (l+1==r) return f[l][r]=1; f[l][r]=0; for (int i=l+1;i<r;i++){ if ((p[r]-p[l])*(p[i]-p[l])<0) (f[l][r]+=(solve(l,i)*solve(i,r))%Mod)%=Mod; } return f[l][r]; } int main(){ int n=read(); for (int i=1;i<=n;i++) p[i].x=read(),p[i].y=read(); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) f[i][j]=-1; double res=0; p[n+1]=p[1]; for (int i=1;i<=n;i++) res+=p[i]*p[i+1]; if (res<0){ for (int i=1;i<=n/2;i++) std::swap(p[i],p[n-i+1]); } printf("%lld\n",solve(1,n)); }