Description
\(n\)个顶点,\(k\)个点,问有多少三角剖分方案满足任意一个三角内都有偶数个点,\(n \leqslant 6\times 10^2,k\leqslant 2\times 10^4\).
Solution
极角排序+DP.
枚举顶点,然后将点按照与这个点形成向量的极角排序,这样可以和其他点形成的三角形是否合法,也就是这一部分一定要有偶数个点才行.
然后就是三角剖分的DP了,\(f[i][j]\) 表示\(i,j\)之间的顶点有多少种剖分方案,然后划分成两部分,来做,记搜会好写些.
复杂度\(O(nklogk+n^3)\)
Code
/************************************************************** Problem: 2087 User: BeiYu Language: C++ Result: Accepted Time:7936 ms Memory:4756 kb ****************************************************************/ #include <bits/stdc++.h> using namespace std; #define mpr make_pair #define x first #define y second typedef pair< int,int > pr; const int N = 650; const int M = 2e4+50; pr operator - (const pr &a,const pr &b) { return mpr(a.x-b.x,a.y-b.y); } int operator * (const pr &a,const pr &b) { return a.x*b.y-a.y*b.x; } inline int in(int x=0,char ch=getchar(),int v=1) { while(ch>'9' || ch<'0') v=(ch=='-'?-1:v),ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return x*v; } int n,k,m; pr B,r[N],p[M]; int f[N][N],g[N][N]; void out(pr a) { cout<<a.x<<" "<<a.y<<endl; } int cmp(const pr &a,const pr &b) { return (a-B)*(b-B)<0; } int DFS(int l,int r) { if(l==r || l+1==r) return f[l][r]=1; if(~f[l][r]) return f[l][r]; f[l][r]=0; for(int i=l+1;i<r;i++) f[l][r]=(f[l][r]+DFS(l,i)*DFS(i,r)*g[l][i]*g[i][r]%m)%m; return f[l][r]; } int main() { // freopen("in.in","r",stdin); n=in(),k=in(),m=in(); for(int i=1;i<=n;i++) { int x=in(),y=in(); r[i]=mpr(x,y); } for(int i=1;i<=k;i++) { int x=in(),y=in(); p[i]=mpr(x,y); } for(int i=1;i<=n;i++) { B=r[i]; sort(p+1,p+k+1,cmp); int s=1; for(int j=i+1;j<=n;j++) { while(s<=k && (r[j]-B)*(p[s]-B)>0) s++; g[i][j]=(s&1)&&((p[s]-B)*(r[j]-B)!=0); } } /* for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { cout<<g[i][j]<<" "; }cout<<endl; }*/ memset(f,0xff,sizeof(f)); cout<<DFS(1,n)<<endl; /* for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { cout<<f[i][j]<<" "; }cout<<endl; }*/ return 0; } /* 5 4 10 5 5 3 0 -1 -1 -3 4 1 10 1 0 -1 0 1 6 -2 5 */