定圆盖点

题型:用一个给定半径的圆覆盖最多的点
#include <bits/stdc++.h>
#define PI acos(-1.0)
struct Point{
    double x, y;
}pt[2005];
double dis[2005][2005];
struct List{
    double a;
    bool flag;
    int id;
}list[8005];
int cnt;
double Dis(int i, int j){
    double dx=pt[i].x-pt[j].x;
    double dy=pt[i].y-pt[j].y;
    return sqrt(dx*dx+dy*dy);
}
int Cmp(const void*p1, const void*p2){
    struct List*a1=(struct List*)p1;
    struct List*a2=(struct List*)p2;			//角度大的先排,角度同的按ID大的先排
    if (a1->a<a2->a)return -1;
    else if (a1->a==a2->a) return a1->id-a2->id;
    else return 1;
}
int main (void){
    int n, i, j, ans, num;
    double r, theta, delta, a1, a2;
    while (scanf("%d %lf",&n,&r)==2){			//n个点,r为定圆半径
        if (n==0&&r==0.0) break;
        r=r+0.001;
        r=r*2.0;
        for (i=1;i<=n;i++)
            scanf("%lf %lf", &pt[i].x, &pt[i].y);		//PT数组存好各个点
        for (i=1;i<n;i++)
            for (j=i+1;j<=n;j++){
                dis[i][j]=Dis(i, j);				//求出任意两点间距离
                dis[j][i]=dis[i][j];
            }
        ans=0;//能覆盖点的总数
        for (i=1;i<=n;i++){
            cnt=0;
            for (j=1;j<=n;j++)					//其他点依次扫一次
                if ((j!=i)&&(dis[i][j]<=r)){			//两个点可以归入圆里
                    theta=atan2(pt[j].y-pt[i].y, pt[j].x-pt[i].x);//连线在绝对极坐标系角度
                    if (theta<0.0) theta=theta+2.0*PI;
                    delta=acos(dis[i][j]/r);				//该点计算圆内临界角度差
                    a1=theta-delta;
                    a2=theta+delta;
                    list[++cnt].a=a1;					//存角度
                    list[cnt].flag=true;					//存标志
                    list[cnt].id=cnt;					//存id
                    list[++cnt].a=a2;
                    list[cnt].flag=false;
                    list[cnt].id=cnt;
                }
            qsort(list+1,cnt,sizeof(struct List),Cmp);
            num=0;
            for (j=1;j<=cnt;j++)
                if (list[j].flag){							//扫一次看被标记的点有少个
                    num++;							//true加false减
                    if (num>ans) ans=num;				//完整循环下来NUM先增后减
                }									//ANS就是记下其峰值
                else num--;
        }
//关键说明:以上这个循环模拟的是以一定点在圆上
//圆在旋转A1的角度是表示覆盖该点的有效点,旋转A2的角度是表示不能再覆盖该点
        printf("It is possible to cover %d points.\n", ans+1);
    }
    return 0;
}
覆盖所有点的面积最小值
一、	不能旋转的矩形覆盖所有点:直接找X,Y坐标MAX与MIN值即可
二、	用多边形覆盖所有点:求凸包然后三角剖分求面积
三、	可以旋转的矩形覆盖所有点:求凸包后旋转卡壳找矩形
四、	用圆形覆盖:见模板

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值