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上的点形成的多边形就是互不干扰的了。
所以初步构思,可以从若干个小弧的状态推到一个大弧的状态。(我可能说不清楚具体过程,感性理解)
还有一个问题就是同颜色的企鹅在同一个多边形内。
这个限制可以转换为,所有的边两侧不存在同颜色的企鹅,且所有企鹅都不在多边形外部。
那么写起来就更方便了。
代码:
#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的更多相关文章
- TopCoder SRM 560 Div 1 - Problem 1000 BoundedOptimization & Codeforces 839 E
传送门:https://284914869.github.io/AEoj/560.html 题目简述: 定义"项"为两个不同变量相乘. 求一个由多个不同"项"相 ...
- TopCoder SRM 558 Div 1 - Problem 1000 SurroundingGame
传送门:https://284914869.github.io/AEoj/558.html 题目简述 一个人在一个n * m棋盘上玩游戏,想要占领一个格子有两个方法: 在这个格子放一个棋子. 这个 ...
- TopCoder SRM 561 Div 1 - Problem 1000 Orienteering
传送门:https://284914869.github.io/AEoj/561.html 题目简述: 题外话: 刚开始看题没看到|C|<=300.以为|C|^2能做,码了好久,但始终解决不了一 ...
- TopCoder SRM 582 Div 1 - Problem 1000 SemiPerfectPower
首先我们可以把答案差分,那么我们只需要求出\(1\)~\(x\)范围内的满足条件的数即可. 题目要求的应该是这个东西的个数: \(l \leq a*b^c \leq r(1 \le a < b) ...
- TopCoder SRM 559 Div 1 - Problem 900 CircusTents
传送门:https://284914869.github.io/AEoj/559.html 题目简述: n个实心圆,两两没有交集,在第一个圆上找一个点,使得它到另外一个圆上某个点的最短距离的最小值尽量 ...
- TopCoder SRM 667 Div.2题解
概览: T1 枚举 T2 状压DP T3 DP TopCoder SRM 667 Div.2 T1 解题思路 由于数据范围很小,所以直接枚举所有点,判断是否可行.时间复杂度O(δX × δY),空间复 ...
- TopCoder SRM 642 Div.2 1000 --二分+BFS
题意: 给你一张图,N个点(0~N-1),m条边,国王要从0到N-1,国王携带一个值,当走到一条边权大于此值的边时,要么不走,要么提升该边的边权,提升k个单位花费k^2块钱,国王就带了B块钱,问能携带 ...
- TopCoder SRM 596 DIV 1 250
body { font-family: Monospaced; font-size: 12pt } pre { font-family: Monospaced; font-size: 12pt } P ...
- Topcoder SRM 656 (Div.1) 250 RandomPancakeStack - 概率+记忆化搜索
最近连续三次TC爆零了,,,我的心好痛. 不知怎么想的,这题把题意理解成,第一次选择j,第二次选择i后,只能从1~i-1.i+1~j找,其实还可以从j+1~n中找,只要没有被选中过就行... [题意] ...
随机推荐
- 详谈C++虚函数表那回事(一般继承关系)
沿途总是会出现关于C++虚函数表的问题,今天做一总结: 1.什么是虚函数表: 虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的.简称为V-Table. ...
- Django 模型层
基本操作 1.meta类属性汇总 属性名 用法 举例代码 abstract 如果设置abstract=True则这个模式是一个抽象基类 db_table 定义model在数据库中的表名称,如果不定 ...
- C实现单链表
typedef int DataType; typedef struct ListNode { DataType data; struct ListNode* next; }ListNode; //初 ...
- 第九条:覆盖equals方法时总要覆盖hashCode方法
Object类的hashCode方法: public native int hashCode(); 是一个本地方法. 其中这个方法的主要注释如下: Whenever it is invoked o ...
- Node入门教程(5)第四章:global 全局变量
global - 全局变量 全局对象(global object),不要和 全局的对象( global objects )或称标准内置对象混淆.这里说的全局的对象是说在全局作用域里的内的对象.全局作用 ...
- 利用Node的chokidar 监听文件改变的文件。
最近维护一个项目.每次改完东西,都要上传到服务器.然后有时候就忘记一些东西,于是就想有没有可以方法能监听文件的改变.然后我再利用程序把更改的文件一键上传到服务器. 于是就找到了nodejs 的chok ...
- emqtt 试用(三)mqtt 知识
一.概念 MQTT 协议客户端库: https://github.com/mqtt/mqtt.github.io/wiki/libraries 例如,mosquitto_sub/pub 命令行发布订阅 ...
- 微信小程序授权获取用户详细信息openid
小程序获取用户的头像昵称openid之类 第一种使用wx.getUserInfo直接获取微信头像,昵称 wx.getUserInfo({ success: function (res) { that. ...
- 一个适用于单页应用,返回原始滚动条位置的demo
如题,最近做一个项目时,由于页面太长,跳转后在返回又回到初始位置,不利于用户体验,需要每次返回到用户离开该页面是的位置.由于是移动端项目,使用了移动端的套ui框架framework7,本身框架的机制是 ...
- 复习HTML+CSS(5)
n <meta>标记 <meta>的主要作用,是提供网页的源信息.比如:指定网页的搜索关键字 <meta>标记有两个属性:http-equiv和name. 1. ...