题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6603
题目大意:给出一个凸包,凸包内有若干个圆,要求画尽可能多的对角线使得他们两两不在凸包内相交且不与任意一个圆有公共点
题解:先预处理出所有点对间的连线是否会和圆有公共点,记为x[i][j],之后进行区间DP。设f[i][d]表示从第(i)个点到(i+d)个点这个区间之内最多能画多少条对角线,那么就有(f[i][d]=x[i][nxt]+max(f[i][d-1],f[i+1][d-1])),答案取f[i][d]的最大值即可
复杂度分析:求凸包(O(nlogn)),预处理(O(n^2g)),DP(O(n^2)),总时间复杂度为(O(n^2g))
吐槽:本题题面又臭又长,严重影响观看体验
给出的(n)个点不一定是凸包的顶点,所以要先求一次凸包,而且这么重要的条件居然是隐藏在巨大题面的一个小括号里的,坑了不少人
最后3分钟才发现这个隐藏条件,赶紧拉了个模板出来最后各种调参数终于在最后一分钟爆过去了orz...
#include<bits/stdc++.h> using namespace std; #define N 401 #define LL long long const double eps=1e-9; int sgn(double x) { if (x<-eps) return -1; if (x>eps) return 1; return 0; } struct Point { double x,y; void read(){scanf("%lf%lf",&x,&y);} Point operator -(const Point &t)const{return {x-t.x,y-t.y};} double operator *(const Point &t)const{return x*t.y-y*t.x;} double length()const{return sqrt(x*x+y*y);} double ang()const { return atan2(1.0*y,1.0*x); } }b[N]; Point cent; bool cmpang(const Point &p1,const Point &p2) { int tmp=sgn( (p1-cent).ang() - (p2-cent).ang() ); if (tmp!=0) return tmp<0; return (p1-cent).length() < (p2-cent).length(); } struct POLYGON { int n; Point a[N]; void ChangetoConvex() { for (int i=2;i<=n;i++) if (a[i].x<a[1].x||a[i].x==a[1].x&&a[i].y<a[1].y) swap(a[1],a[i]); cent=a[1]; sort(a+2,a+n+1,cmpang); int top=2; for (int i=3;i<=n;i++) { while(top>=2&& (a[top]-a[top-1])*(a[i]-a[top])<=0 ) top--; a[++top]=a[i]; } n=top; } }P; int T,n,g,r,x[N][N],f[N][N]; bool check(int x,int y) { if(x%n+1==y || y%n+1==x) return false; double dis=(P.a[x]-P.a[y]).length(); for(int i=1;i<=g;i++) { double cha=abs((P.a[y]-P.a[x])*(b[i]-P.a[x])); if(cha+eps<=1.0*r*dis)return false; } return true; } void init() { int ans=0; memset(f,0,sizeof(f)); scanf("%d%d%d",&n,&g,&r); P.n=n; for(int i=1;i<=n;i++) P.a[i].read(); for(int i=1;i<=g;i++) b[i].read(); P.ChangetoConvex(); n=P.n; for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) x[i][j]=x[j][i]=check(i,j); for(int d=2;d<=n-2;d++) for(int i=1;i<=n;i++) { int nxt=(i+d-1)%n+1,res=0; res=max(f[i][d-1],f[i%n+1][d-1]); f[i][d]=x[i][nxt]+res; ans=max(ans,f[i][d]); } printf("%d ",ans); } int main() { scanf("%d",&T); while(T--)init(); }