TopCoder SRM 566 Div 1 - Problem 1000 FencingPenguins

传送门:https://284914869.github.io/AEoj/566.html

题目简述:

平面上有中心在原点,一个点在(r,0)处的正n边形的n个顶点。
平面上还有m个企鹅,每个企鹅有一个位置和一个颜色,
现在要连一些边,使得每个点的度数都是0或2,
这样会构成若干个顶点不相交的圈,求满足以下条件的连边方案数:
1、每个圈里有至少一个企鹅;
2、任意两个圈不相交;
3、每种颜色的企鹅在同一个有限区域中;
4、每个企鹅在一个有限区域内;
n<=222,m<=50,r<=10^5, 
企鹅的颜色保证是大写字母或者小写字母,
坐标范围<=10^5,企鹅离任一条n个点连的边的距离>10^-6

思路:

很显然这题要用dp。考虑怎么用dp做。

 

如图所示

我们先定义“特殊”多边形为有>=3条边的多边形或一个点。如图有6个多边形(包括点E)。

这样所有的点就都在多边形上了。

我们选任意一个点作为起点。例如D。

D所在的多边形为DGHI。这样弧DG,GH,HI,ID上的点形成的多边形就是互不干扰的了。

所以初步构思,可以从若干个小弧的状态推到一个大弧的状态。(我可能说不清楚具体过程,感性理解)

还有一个问题就是同颜色的企鹅在同一个多边形内。

这个限制可以转换为,所有的边两侧不存在同颜色的企鹅,且所有企鹅都不在多边形外部。

那么写起来就更方便了。

代码:

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <string>
  4 #include <vector>
  5 #include <cstring>
  6 #include <iostream>
  7 #include <algorithm>
  8 using namespace std;
  9 #define _CLASSNAME_ FencingPenguins
 10 #define _METHODNAME_ countWays
 11 #define _RC_ int
 12 #define _METHODPARMS_ int _n, int _r, vector<int> _x, vector<int> _y, string _c
 13 #define ref(i,x,y)for(int i=x;i<=y;++i)
 14 #define def(i,x,y)for(int i=x;i>=y;--i)
 15 #define reset(a)memset(a,0,sizeof a)
 16 const double pi=acos(-1);
 17 const int mod=100007;
 18 struct point{
 19     double x,y;
 20     point(){x=0;y=0;}
 21     point(double X,double Y){x=X,y=Y;}
 22 };
 23 point operator -(point a,point b){ return point(a.x-b.x,a.y-b.y); }
 24 double operator ^(point a,point b){ return a.y*b.x-a.x*b.y; }
 25 int n,m,r,ans;
 26 int p_c[51],fg[52],sum[445][445];
 27 point O[301],p[51];
 28 bool ok[445][445];
 29 void inc(int&a,int b){a+=b;if(a>=mod)a-=mod;}
 30 int mul(int a,int b){return 1LL*a*b%mod;}
 31 int chd(char c){if(c>='a'&&c<='z')return c-'a';else return c-'A'+26;}
 32 void work1(){
 33     reset(ok); reset(sum); ans=0;
 34     ref(i,0,n-1) O[i]=point(r*cos(2*pi*i/n),r*sin(2*pi*i/n));
 35     ref(i,0,n-1)ok[i][i]=1;
 36     ref(i,0,n-1)ref(j,i+1,n-1){
 37         ref(k,0,51)fg[k]=0;
 38         ref(k,1,m){
 39             int C=p_c[k]; double s=(O[j]-O[i])^(p[k]-O[i]); 
 40             if(!fg[C])fg[C]=(s>0)+1;else if(fg[C]!=-1) if(fg[C]!=(s>0)+1)fg[C]=-1;
 41             sum[i][j]+=(s>0);
 42         }
 43         bool flag=1; ref(k,0,51)flag=flag&&(fg[k]>=0);    
 44         ok[i][j]=ok[j][i]=flag; sum[j][i]=m-sum[i][j];
 45     }
 46     ref(i,0,n-1)ref(j,0,n-1) sum[i+n][j]=sum[i][j+n]=sum[i+n][j+n]=sum[i][j];
 47     ref(i,0,n-1)ref(j,0,n-1) ok[i+n][j]=ok[i][j+n]=ok[i+n][j+n]=ok[i][j];
 48 }
 49 int dp1[445][445][2],dp2[445][445]; bool tri[223][445][445];
 50 void work2()
 51 {
 52     reset(dp1); reset(dp2); reset(tri);
 53     ref(i,0,n-1)if(sum[i][i+1])return;
 54     ref(i,0,n-1)ref(j,i,i+n-1)ref(k,i+1,j-1)tri[i][k][j]=(sum[i][j]-sum[i][k]-sum[k][j]>0);
 55     ref(i,0,n*2-1)dp1[i][i][1]=1,dp2[i][i]=1;
 56     ref(len,1,n-1){
 57         ref(i,0,n-1){
 58             int j=i+len;
 59             ref(k,i,j-1) if(!tri[i][k+1][j]&&!tri[i][j][j+1])
 60                 if(ok[k+1][j])inc(dp2[i][j],mul(dp2[i][k],dp1[k+1][j][1]));
 61             inc(dp1[i][j][0],dp2[i][j-1]);
 62             ref(k,i+1,j-1)ref(d,0,1) 
 63                 inc(dp1[i][j][d|tri[i][k][j]],mul(dp1[i][k][d],dp2[k][j-1]));
 64             if(j<n)dp1[i+n][j+n][0]=dp1[i][j][0],dp1[i+n][j+n][1]=dp1[i][j][1];
 65             if(j<n)dp2[i+n][j+n]=dp2[i][j];
 66         }
 67     }
 68     if(!tri[n-1][n][n+1])ans=dp2[0][n-1];
 69     ref(i,2,n-1)if(ok[0][i])inc(ans,mul(dp1[0][i][1],dp2[i][n-1]));
 70 }
 71 class _CLASSNAME_{
 72 public:
 73     _RC_ _METHODNAME_(_METHODPARMS_)
 74     {
 75         n=_n; m=_x.size(); r=_r;
 76         ref(i,1,m)p[i].x=_x[i-1],p[i].y=_y[i-1];
 77         ref(i,1,m)p_c[i]=chd(_c[i-1]);
 78         work1();work2();
 79         return _RC_(ans);
 80     }
 81     
 82 // BEGIN CUT HERE
 83     public:
 84     void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); if ((Case == -1) || (Case == 5)) test_case_5(); if ((Case == -1) || (Case == 6)) test_case_6(); if ((Case == -1) || (Case == 7)) test_case_7(); }
 85     private:
 86     //template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
 87     void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
 88     void test_case_0() { int Arg0 = 4; int Arg1 = 10; int Arr2[] = {2}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arr3[] = {1}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[0]))); string Arg4 = "R"; int Arg5 = 3; verify_case(0, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
 89     void test_case_1() { int Arg0 = 4; int Arg1 = 10; int Arr2[] = {2,-2}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arr3[] = {1,-1}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[0]))); string Arg4 = "RR"; int Arg5 = 1; verify_case(1, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
 90     void test_case_2() { int Arg0 = 8; int Arg1 = 10; int Arr2[] = {8,-8,-8,8}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arr3[] = {1,-1,1,-1}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[0]))); string Arg4 = "BBBB"; int Arg5 = 25; verify_case(2, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
 91     void test_case_3() { int Arg0 = 8; int Arg1 = 10; int Arr2[] = {8,-8,-8,8}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arr3[] = {1,-1,1,-1}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[0]))); string Arg4 = "RGBY"; int Arg5 = 50; verify_case(3, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
 92     void test_case_4() { int Arg0 = 6; int Arg1 = 5; int Arr2[] = {0,0}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arr3[] = {-4,4}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[0]))); string Arg4 = "rB"; int Arg5 = 6; verify_case(4, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
 93     void test_case_5() { int Arg0 = 3; int Arg1 = 5; int Arr2[] = {4}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arr3[] = {3}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[0]))); string Arg4 = "y"; int Arg5 = 0; verify_case(5, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
 94     void test_case_6() { int Arg0 = 200; int Arg1 = 100000; int Arr2[] = {1020,30203,2302,203,-12321,-21332,8823,-2133,2323}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arr3[] = {-123,2131,4434,1223,43434,2323,4343,-213,-2325}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[0]))); string Arg4 = "YBYBWWBRr"; int Arg5 = 27547; verify_case(6, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
 95     void test_case_7() { int Arg0 = 222; int Arg1 = 1713; int Arr2[] = {1091, 243, 505, 510, 869, 700, 790, 70, 260, 177, 273, 9, 43, -83, -163, -79, -352, -231, -663, -8, -768, -128, -768, -372, -577, -895, -994, -564, -509, -199, -833, -391, -445, -276, -115, -133, -166, -37, 65, 170, 251, 389, 23, 194, 130, 629, 477, 401, 1080, 36}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arr3[] = {4, 147, 265, 52, 302, 548, 183, 302, 439, 176, 167, 287, 677, 826, 156, 550, 758, 129, 254, 308, 595, 445, 310, 230, 99, -3, -85, -113, -321, -99, -134, -98, -747, -615, -216, -760, -891, -248, -783, -396, -586, -866, -479, -50, -731, -50, -195, -153, -23, -9}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[0]))); string Arg4 = "xidylnzmnsolwfyhgjaegnwgazjbdmfwaldsmqxpowtianiesx"; int Arg5 = 64346; verify_case(7, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
 96 // END CUT HERE
 97 
 98 };
 99 // BEGIN CUT HERE
100 int main()
101 {
102     _CLASSNAME_ user;
103     user.run_test(-1);
104 }
105 // END CUT HERE

 

posted @ 2017-11-17 16:59  I_m_Eden  阅读(623)  评论(0编辑  收藏  举报