传送门: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上的点形成的多边形就是互不干扰的了。

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

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

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

那么写起来就更方便了。

代码:

 #include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define _CLASSNAME_ FencingPenguins
#define _METHODNAME_ countWays
#define _RC_ int
#define _METHODPARMS_ int _n, int _r, vector<int> _x, vector<int> _y, string _c
#define ref(i,x,y)for(int i=x;i<=y;++i)
#define def(i,x,y)for(int i=x;i>=y;--i)
#define reset(a)memset(a,0,sizeof a)
const double pi=acos(-);
const int mod=;
struct point{
double x,y;
point(){x=;y=;}
point(double X,double Y){x=X,y=Y;}
};
point operator -(point a,point b){ return point(a.x-b.x,a.y-b.y); }
double operator ^(point a,point b){ return a.y*b.x-a.x*b.y; }
int n,m,r,ans;
int p_c[],fg[],sum[][];
point O[],p[];
bool ok[][];
void inc(int&a,int b){a+=b;if(a>=mod)a-=mod;}
int mul(int a,int b){return 1LL*a*b%mod;}
int chd(char c){if(c>='a'&&c<='z')return c-'a';else return c-'A'+;}
void work1(){
reset(ok); reset(sum); ans=;
ref(i,,n-) O[i]=point(r*cos(*pi*i/n),r*sin(*pi*i/n));
ref(i,,n-)ok[i][i]=;
ref(i,,n-)ref(j,i+,n-){
ref(k,,)fg[k]=;
ref(k,,m){
int C=p_c[k]; double s=(O[j]-O[i])^(p[k]-O[i]);
if(!fg[C])fg[C]=(s>)+;else if(fg[C]!=-) if(fg[C]!=(s>)+)fg[C]=-;
sum[i][j]+=(s>);
}
bool flag=; ref(k,,)flag=flag&&(fg[k]>=);
ok[i][j]=ok[j][i]=flag; sum[j][i]=m-sum[i][j];
}
ref(i,,n-)ref(j,,n-) sum[i+n][j]=sum[i][j+n]=sum[i+n][j+n]=sum[i][j];
ref(i,,n-)ref(j,,n-) ok[i+n][j]=ok[i][j+n]=ok[i+n][j+n]=ok[i][j];
}
int dp1[][][],dp2[][]; bool tri[][][];
void work2()
{
reset(dp1); reset(dp2); reset(tri);
ref(i,,n-)if(sum[i][i+])return;
ref(i,,n-)ref(j,i,i+n-)ref(k,i+,j-)tri[i][k][j]=(sum[i][j]-sum[i][k]-sum[k][j]>);
ref(i,,n*-)dp1[i][i][]=,dp2[i][i]=;
ref(len,,n-){
ref(i,,n-){
int j=i+len;
ref(k,i,j-) if(!tri[i][k+][j]&&!tri[i][j][j+])
if(ok[k+][j])inc(dp2[i][j],mul(dp2[i][k],dp1[k+][j][]));
inc(dp1[i][j][],dp2[i][j-]);
ref(k,i+,j-)ref(d,,)
inc(dp1[i][j][d|tri[i][k][j]],mul(dp1[i][k][d],dp2[k][j-]));
if(j<n)dp1[i+n][j+n][]=dp1[i][j][],dp1[i+n][j+n][]=dp1[i][j][];
if(j<n)dp2[i+n][j+n]=dp2[i][j];
}
}
if(!tri[n-][n][n+])ans=dp2[][n-];
ref(i,,n-)if(ok[][i])inc(ans,mul(dp1[][i][],dp2[i][n-]));
}
class _CLASSNAME_{
public:
_RC_ _METHODNAME_(_METHODPARMS_)
{
n=_n; m=_x.size(); r=_r;
ref(i,,m)p[i].x=_x[i-],p[i].y=_y[i-];
ref(i,,m)p_c[i]=chd(_c[i-]);
work1();work2();
return _RC_(ans);
} // BEGIN CUT HERE
public:
void run_test(int Case) { if ((Case == -) || (Case == )) test_case_0(); if ((Case == -) || (Case == )) test_case_1(); if ((Case == -) || (Case == )) test_case_2(); if ((Case == -) || (Case == )) test_case_3(); if ((Case == -) || (Case == )) test_case_4(); if ((Case == -) || (Case == )) test_case_5(); if ((Case == -) || (Case == )) test_case_6(); if ((Case == -) || (Case == )) test_case_7(); }
private:
//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(); }
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; } }
void test_case_0() { int Arg0 = ; int Arg1 = ; int Arr2[] = {}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[]))); int Arr3[] = {}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[]))); string Arg4 = "R"; int Arg5 = ; verify_case(, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
void test_case_1() { int Arg0 = ; int Arg1 = ; int Arr2[] = {,-}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[]))); int Arr3[] = {,-}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[]))); string Arg4 = "RR"; int Arg5 = ; verify_case(, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
void test_case_2() { int Arg0 = ; int Arg1 = ; int Arr2[] = {,-,-,}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[]))); int Arr3[] = {,-,,-}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[]))); string Arg4 = "BBBB"; int Arg5 = ; verify_case(, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
void test_case_3() { int Arg0 = ; int Arg1 = ; int Arr2[] = {,-,-,}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[]))); int Arr3[] = {,-,,-}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[]))); string Arg4 = "RGBY"; int Arg5 = ; verify_case(, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
void test_case_4() { int Arg0 = ; int Arg1 = ; int Arr2[] = {,}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[]))); int Arr3[] = {-,}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[]))); string Arg4 = "rB"; int Arg5 = ; verify_case(, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
void test_case_5() { int Arg0 = ; int Arg1 = ; int Arr2[] = {}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[]))); int Arr3[] = {}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[]))); string Arg4 = "y"; int Arg5 = ; verify_case(, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
void test_case_6() { int Arg0 = ; int Arg1 = ; int Arr2[] = {,,,,-,-,,-,}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[]))); int Arr3[] = {-,,,,,,,-,-}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[]))); string Arg4 = "YBYBWWBRr"; int Arg5 = ; verify_case(, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
void test_case_7() { int Arg0 = ; int Arg1 = ; int Arr2[] = {, , , , , , , , , , , , , -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, , , , , , , , , , , , }; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[]))); int Arr3[] = {, , , , , , , , , , , , , , , , , , , , , , , , , -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -, -}; vector <int> Arg3(Arr3, Arr3 + (sizeof(Arr3) / sizeof(Arr3[]))); string Arg4 = "xidylnzmnsolwfyhgjaegnwgazjbdmfwaldsmqxpowtianiesx"; int Arg5 = ; verify_case(, Arg5, countWays(Arg0, Arg1, Arg2, Arg3, Arg4)); }
// END CUT HERE };
// BEGIN CUT HERE
int main()
{
_CLASSNAME_ user;
user.run_test(-);
}
// END CUT HERE

TopCoder SRM 566 Div 1 - Problem 1000 FencingPenguins的更多相关文章

  1. TopCoder SRM 560 Div 1 - Problem 1000 BoundedOptimization & Codeforces 839 E

    传送门:https://284914869.github.io/AEoj/560.html 题目简述: 定义"项"为两个不同变量相乘. 求一个由多个不同"项"相 ...

  2. TopCoder SRM 558 Div 1 - Problem 1000 SurroundingGame

    传送门:https://284914869.github.io/AEoj/558.html 题目简述  一个人在一个n * m棋盘上玩游戏,想要占领一个格子有两个方法: 在这个格子放一个棋子.  这个 ...

  3. TopCoder SRM 561 Div 1 - Problem 1000 Orienteering

    传送门:https://284914869.github.io/AEoj/561.html 题目简述: 题外话: 刚开始看题没看到|C|<=300.以为|C|^2能做,码了好久,但始终解决不了一 ...

  4. TopCoder SRM 582 Div 1 - Problem 1000 SemiPerfectPower

    首先我们可以把答案差分,那么我们只需要求出\(1\)~\(x\)范围内的满足条件的数即可. 题目要求的应该是这个东西的个数: \(l \leq a*b^c \leq r(1 \le a < b) ...

  5. TopCoder SRM 559 Div 1 - Problem 900 CircusTents

    传送门:https://284914869.github.io/AEoj/559.html 题目简述: n个实心圆,两两没有交集,在第一个圆上找一个点,使得它到另外一个圆上某个点的最短距离的最小值尽量 ...

  6. TopCoder SRM 667 Div.2题解

    概览: T1 枚举 T2 状压DP T3 DP TopCoder SRM 667 Div.2 T1 解题思路 由于数据范围很小,所以直接枚举所有点,判断是否可行.时间复杂度O(δX × δY),空间复 ...

  7. TopCoder SRM 642 Div.2 1000 --二分+BFS

    题意: 给你一张图,N个点(0~N-1),m条边,国王要从0到N-1,国王携带一个值,当走到一条边权大于此值的边时,要么不走,要么提升该边的边权,提升k个单位花费k^2块钱,国王就带了B块钱,问能携带 ...

  8. TopCoder SRM 596 DIV 1 250

    body { font-family: Monospaced; font-size: 12pt } pre { font-family: Monospaced; font-size: 12pt } P ...

  9. Topcoder SRM 656 (Div.1) 250 RandomPancakeStack - 概率+记忆化搜索

    最近连续三次TC爆零了,,,我的心好痛. 不知怎么想的,这题把题意理解成,第一次选择j,第二次选择i后,只能从1~i-1.i+1~j找,其实还可以从j+1~n中找,只要没有被选中过就行... [题意] ...

随机推荐

  1. python中functools.singledispatch的使用

    from functools import singledispatch @singledispatch def show(obj): print (obj, type(obj), "obj ...

  2. Swift -欢迎界面1页, 延长启动图片的显示时间(LaunchImage)

    转自:http://www.hangge.com/blog/cache/detail_1238.html http://www.hangge.com/blog/cache/detail_672.htm ...

  3. poj 2142 The Balance

    The Balance http://poj.org/problem?id=2142 Time Limit: 5000MS   Memory Limit: 65536K       Descripti ...

  4. 成功案例分享:raid5两块硬盘掉线数据丢失恢复方法

    1. 故障描述    本案例是HP P2000的存储vmware exsi虚拟化平台,由RAID-5由10块lT硬盘组成,其中6号盘是热备盘,由于故障导致RAID-5磁盘阵列的两块盘掉线,表现为两块硬 ...

  5. JavaScript Cookie使用实例

    # Session-Cookie //  利用Cookie防止在1分钟内多次提交: function SetCookie (name, value) { var Days = 30; var exp ...

  6. web api 如何通过接收文件流的方式,接收客户端及前端上传的文件

    服务端接收文件流代码: public async Task<HttpResponseMessage> ReceiveFileByStream() { var stream = HttpCo ...

  7. Struts2 配置文件小结

    每次写的博文都被管理员都被移出首页,好气!还希望有哪位大神可以指点迷津-- struts2 配置文件的 result 节点 result 节点是 action 节点的子节点,他代表着 action 方 ...

  8. iot前台开发环境:前后台访问映射

    一.前端映射- java代码 二.路由设置 -前台代码 三.访问应用

  9. jquery下关于input和label的关于点击事件的坑

    待填坑: 法院费用结算页面的案件类型

  10. CSS中容易混淆的伪元素类型和用法

    :first-of-type 匹配属于其父元素的第一个特定类型的子元素. 1.例子 <head> <meta charset="UTF-8"> <ti ...