2019 多校第三场A , 简单计算几何+简单dp
明明n<=400还10组数据,出题人硬说凸包上的点不会很多n^3可过,害我想一整场怎么优化。
题意:n个平面上的木桩,你要选出尽可能多的以凸包上两个不相邻木桩为顶点的线,使这些线互不相交而且不能与给定的g个圆相交。
把与圆相交的线去掉,然后做一个简单的区间dp即可。
/*
Author: fffasttime
Date:
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inc(i,n) for (int i=0;i<n;i++)
const int N=100010;
typedef double db;
const db eps=1e-9;
bool eq(db x){return fabs(x)<eps;}
#define Vec const vec &
#define Point const point &
struct vec{
db x,y;
vec operator+(Vec v)const{return {x+v.x,y+v.y};}
vec operator-(Vec v)const{return {x-v.x,y-v.y};}
vec operator*(db t)const{return {x*t,y*t};}
vec operator/(db t)const{return {x/t,y/t};}
db operator|(Vec v)const{return x*v.x+y*v.y;}
db operator&(Vec v)const{return x*v.y-y*v.x;}
db operator!()const{return sqrt(x*x+y*y);}
bool operator<(vec v)const{
return eq(x-v.x)?y<v.y:x<v.x;
}
void rd(){
scanf("%lf%lf",&x,&y);
}
void prt(){printf("%f %f\n",x,y);}
};
typedef vec point;
db cross(Vec a, Vec b, Vec c){return b-a&c-a;}
int convex(point *p, int n, point *ans){
sort(p,p+n);
int m=0;
for (int i=0;i<n;i++){
while (m>1 && cross(ans[m-2],ans[m-1],p[i])<=0) m--;
ans[m++]=p[i];
}
int k=m;
for (int i=n-2;i>=0;i--){
while (m>k && cross(ans[m-2],ans[m-1],p[i])<=0) m--;
ans[m++]=p[i];
}
if (n>1) m--;
return m;
}
db linedis(Vec p, Vec a, Vec b){
vec v1=b-a, v2=p-a;
return fabs(v1&v2/!v1);
}
point p0[500],p[500],gr[110];
bool a[500][500];
int dp[500][500];
int main(){
int T; scanf("%d",&T);
while (T--){
int n,g,r;
scanf("%d%d%d",&n,&g,&r);
inc(i,n) p0[i].rd();
inc(i,g) gr[i].rd();
n=convex(p0,n,p);
if (n<4){
puts("0");
continue;
}
//for (int i=0;i<n;i++) p[i].prt();
memset(a,0,sizeof a);
for (int i=0;i<n;i++)
for (int j=i+1;j<n;j++){
for (int k=0;k<g;k++)
if (linedis(gr[k],p[i],p[j])<=r)
goto fail;
a[i][j]=a[j][i]=1;
fail:;
}
memset(dp,0,sizeof dp);
for (int i=0;i<n;i++) a[i][(i+1)%n]=a[i][(i-1+n)%n]=0;
for (int k=2;k<n;k++)
for (int i=0;i+k<n;i++){
for (int j=i+1;j<i+k;j++){
dp[i][i+k]=max(dp[i][i+k],dp[i][j]+dp[j][i+k]+a[i][i+k]);
}
}
//for (int i=0;i<n;i++,puts(""))
// for (int j=0;j<n;j++) cout<<a[i][j]<<' ';
cout<<dp[0][n-1]<<'\n';
}
return 0;
}