hdu6603 Azshara's deep sea (计算几何+区间DP)

hdu6603 Azshara’s deep sea(2019hdu多校第三场1001)

【题目描述】

传送带
汗!感觉读题时间比想题时间还长
大概意思是wood stick(可视为顶点)围成了一个battle field,players可以在这个围成的battle field中(含边界)活动,另外这个区域内还有一些圆,现在有个boss要选若干对player并且把他们放在顶点,并用直线把他们连在一起,这些连线要满足两个条件:1)不可以和区域内的圆相切或相交,2)两两之间不可以相交(但端点可以相同)3)一对play不可以在相邻的顶点上
求boss最多可以选出多少对player

【思考】

其实就是选若干对不相邻的顶点,不相交,不经过圆。
先维护出一个凸包,预处理每条线段是否不经过圆,对于一条线段check的时间是O(G)(G是圆的个数),这些时间复杂度都不高,所以重点在于选哪些线段使他们两两不相交,有种三角剖分的冲动(也是三角不能相交或交于一边),而且顶点数也不大,所以就用区间dp来解决
转移方程是
dp[i][j]=max{dp[i][j],dp[i][t]+dp[t][j]+rel[i][j]} (i rel是预处理的顶点ij连边是否不经过所有圆
注意t不等于i或j,否则会重复计算

这题计算几何的部分参考了另一篇博客
传送带
这篇博客处理区间dp似乎是把原来的区间延长来得到一个循环,不过还是没有太看懂膜一下大佬

【代码】
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int MAXN=4e2+10;
const double eps=1e-10;
const double pi=acos(-1.0);
const ll INF=0x3f3f3f3f3f3f3f3f;
int T;
int N,R,G;
int dp[MAXN][MAXN];
int rel[MAXN][MAXN];
inline double sqr(double x){
	return x*x;
}
inline int dcmp(double x){
	if(fabs(x)0?1:-1;
}
struct Point{
	double x,y;
	Point(){x=0,y=0;}
	Point(double _x,double _y):x(_x),y(_y){}
	void input(){scanf("%lf%lf",&x,&y);}
	void output(){printf("%.2lf %.2lf\n",x,y);}
	bool operator ==(const Point &b)const{
		return (dcmp(x-b.x)==0&&dcmp(y-b.y)==0);
	}
	bool operator !=(const Point &b)const{
		return !(dcmp(x-b.x)==0&&dcmp(y-b.y)==0);
	}
	bool operator <(const Point &b)const{
		return (dcmp(x-b.x)==0?dcmp(y-b.y)<0:x1&&dcmp(cross(tmp[m-1]-tmp[m-2],p[i]-tmp[m-1]))<=0) m--;
		tmp[m++]=p[i];
	}
	int k=m;
	for(int i=n-2;i>=0;i--){
		while(m>k&&dcmp(cross(tmp[m-1]-tmp[m-2],p[i]-tmp[m-1]))<=0) m--;
		tmp[m++]=p[i];
	} 
	if(n>1) m--;
	for(int i=0;i

你可能感兴趣的:(区间DP,计算几何,hdu)