hdu 6603 Azshara's deep sea

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6603

题目大意是:给你n个点,g的圆  圆给的是圆心。然后在这n个点求一个凸包,在凸包不相邻的两点并且与圆不相交找到直线。

找到凸包上所有不相交直线的最大数。

这里判断直线和圆的关系使用了面积判断,画个图就知道了。

#include<bits/stdc++.h>
#define ll long long
using namespace  std;

const double eps = 1e-10;
double dcmp(double x) {
    if(fabs(x) < eps) return 0;
    else return x < 0 ? -1 : 1;
}
 
struct Point {
    double x, y;
    Point(double x=0, double y=0):x(x),y(y) {}
}b[401];

typedef Point Vector;
 
Vector operator - (const Point& A, const Point& B) {
    return Vector(A.x-B.x, A.y-B.y);
}
 
double Cross(const Vector& A, const Vector& B) {
    return A.x*B.y - A.y*B.x;
}

 
double distance(double x1,double y1,double x2,double y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
 
double Dot(const Vector& A, const Vector& B) {
    return A.x*B.x + A.y*B.y;
}
 
bool operator < (const Point& p1, const Point& p2) {
    return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y);
}
 
bool operator == (const Point& p1, const Point& p2) {
    return p1.x == p2.x && p1.y == p2.y;
}
 
bool SegmentProperIntersection(const Point& a1, const Point& a2, const Point& b1, const Point& b2) {
    double c1 = Cross(a2-a1,b1-a1), c2 = Cross(a2-a1,b2-a1),
           c3 = Cross(b2-b1,a1-b1), c4=Cross(b2-b1,a2-b1);
    return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
}
 
bool OnSegment(const Point& p, const Point& a1, const Point& a2) {
    return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;
}
 
// 点集凸包
// 如果不希望在凸包的边上有输入点,把两个 <= 改成 <
// 如果不介意点集被修改,可以改成传递引用
vector<Point> ConvexHull(vector<Point> p) {
    // 预处理,删除重复点
    sort(p.begin(), p.end());
    p.erase(unique(p.begin(), p.end()), p.end());
 
    int n = p.size();
    int m = 0;
    vector<Point> ch(n+1);
    for(int i = 0; i < n; i++) {
        while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
        ch[m++] = p[i];
    }
    int k = m;
    for(int i = n-2; i >= 0; i--) {
        while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
        ch[m++] = p[i];
    }
    if(n > 1) m--;
    ch.resize(m);
    return ch;
}
int e[500][500],f[405][405];
int main(){
	int t;
	scanf("%d",&t);
	double  x,y;
	int n,g,r;
	while(t--){
		int  ans=0;
		scanf("%d%d%d",&n,&g,&r);
		vector<Point> v;
		for(int i=0;i<n;i++){
			scanf("%lf %lf",&x,&y);
			v.push_back({x,y});
		}
		v = ConvexHull(v);
		for(int i=1;i<=g;i++){
			scanf("%lf %lf",&b[i].x,&b[i].y);
		}
		int len=v.size();
		//得到不与圆相交和相切的不相邻2点 标记为1为可行直线 
		for(int i=0;i<len;i++){
			for(int j=i+1;j<len;j++){
				if(i==0&&j==len-1){
					continue;
				}
				e[i+1][j+1]=e[j+1][i+1]=1;
				double dis = distance(v[i].x,v[i].y,v[j].x,v[j].y);
				for(int k=1;k<=g;k++){
					double cha = abs( Cross(v[i]-v[j],(v[i]-b[k])) );
					if(cha + eps <= 1.0*dis*r){
						e[i+1][j+1]=e[j+1][i+1]=0;
						break;
					}
				} 
			}
		}
		//最后区间dp 找到不相交的 最大直线数 
		for(int i=2;i<=len-2;i++){
			for(int j=1;j<=len;j++){
				int nex = (i+j-1)%n+1,res=0;
				res = max(f[j][i-1] ,f[j%len+1][i-1]);
				f[j][i] = e[j][nex] + res;
				ans = max(ans,f[j][i]); 
			}
		}
		printf("%d\n",ans);
		memset(e,0,sizeof(e));
	} 
		
} 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值