zoukankan      html  css  js  c++  java
  • TopCoder SRM 566 Div 1

    传送门: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 << "	Expected: "" << Expected << '"' << endl; cerr << "	Received: "" << 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
  • 相关阅读:
    合适的适配器的最佳模式
    poj3414--Pots(bfs,记录路径)
    HTML与XHTML差额
    获得球——采访拼图
    3-08. 栈模拟队列(25)(ZJU_PAT 模拟)
    学习内核驱动程序的错误及其解决方案的出现,
    Objective-C中的Block
    Objective-C语法之代码块(block)的使用
    ObjectiveC中的block用法解析
    使用Swift的代理,闭包来封装一个公用协议减少垃圾代码
  • 原文地址:https://www.cnblogs.com/Blog-of-Eden/p/7852426.html
Copyright © 2011-2022 走看看