题目练习_球面距离_圆覆盖点

球面距离

题目大意

给定两个点的经度和纬度,求两个点的球面距离,半径为地球半径6370km。经度和纬度给定分和秒,需要转化。

代码

主要就是要学习球面距离的求法,即转化为圆心角和半径的乘积。

#include <iostream>
#include <bits/stdc++.h>

#define INF 0x3f3f3f3f
#define pi 3.141592653589793238462643383279

using namespace std;
typedef long long ll;
const int lmax = 5e3 + 10;
const int mod = 1e9 + 7;

double sph_dis(double wd1,double jd1,double wd2,double jd2,double r)//已知纬度,经度,半径,求球面两点之间的球上距离
{//经度和纬度都转换成弧度制
    double x1,x2,y1,y2,z1,z2;
    x1=cos(wd1)*cos(jd1);
    y1=cos(wd1)*sin(jd1);
    z1=sin(wd1);
    x2=cos(wd2)*cos(jd2);
    y2=cos(wd2)*sin(jd2);
    z2=sin(wd2);
    double a=acos(x1*x2+y1*y2+z1*z2);//圆心角
    return r*a;
}
int main()
{
    double w1,wm1,j1,jm1,wd1,jd1;
    double w2,wm2,j2,jm2,wd2,jd2;
    char chr1,chr2;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lf %lf %c %lf %lf %c",&w1,&wm1,&chr1,&j1,&jm1,&chr2);
        wd1=(w1+wm1/60)*pi/180;
        jd1=(j1+jm1/60)*pi/180;
        if(chr1=='S')
            wd1*=-1.0;
        if(chr2=='W')
            jd1*=-1.0;
        scanf("%lf %lf %c %lf %lf %c",&w2,&wm2,&chr1,&j2,&jm2,&chr2);
        wd2=(w2+wm2/60)*pi/180;
        jd2=(j2+jm2/60)*pi/180;
        if(chr1=='S')
            wd2*=-1.0;
        if(chr2=='W')
            jd2*=-1.0;
        printf("%.3lf\n",sph_dis(wd1,jd1,wd2,jd2,6370.0));
    }
    return 0;
}
/*
2
55 0 N 40 0 E
59 0 N 49 30 E
40 0 N 0 0 E
40 0 N 180 0 E
*/

圆覆盖点

题目大意

在二维平面给定很多点,问一个单位圆最多能覆盖多少点。

代码

#include <iostream>
#include <bits/stdc++.h>

#define INF 0x3f3f3f3f
#define pi 3.141592653589793238462643383279
#define eps 1e-6
using namespace std;
typedef long long ll;
struct Point
{
    double x,y;
}point[301];
double dis(Point p1,Point p2)//两点间距离的平方
{
    return (p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y);
}

Point find_start(Point p1,Point p2)
{
    Point p,mid,start;
    double d,aa;
    p.x=p2.x-p1.x;
    p.y=p2.y-p1.y;
    mid.x=(p1.x+p2.x)/2;
    mid.y=(p1.y+p2.y)/2;
    d=sqrt(1-dis(p1,mid));
    if(fabs(p.y)<eps)//公共弦垂直于X轴
    {
        start.x=mid.x;
        start.y=mid.y+d;
    }
    else//公共弦不垂直于X轴
    {
        aa=atan(-p.x/p.y);//公共弦的倾斜角
        start.x=mid.x+d*cos(aa);
        start.y=mid.y+d*sin(aa);
    }
    return start;
}
int main()
{
    int n,ans,ans0;
    int i,j,k;
    Point centre;
    double tmp;
    while(~scanf("%d",&n))
    {
        if(n==0)
            break;
        for(i=0;i<n;i++)
        {
            scanf("%lf%lf",&point[i].x,&point[i].y);
        }
        ans=1;
        for(i=0;i<n;i++)
            for(j=i+1;j<n;j++)
            {
                if(dis(point[i],point[j])>4)
                    continue;
                ans0=0;
                centre=find_start(point[i],point[j]);
                for(k=0;k<n;k++)
                {
                    tmp=dis(centre,point[k]);
                    if(tmp<=1.000001)
                        ans0++;
                }
                if(ans<ans0)
                    ans=ans0;
            }
        printf("%d\n",ans);
    }
    return 0;
}
/*
3
6.47634 7.69628
5.16828 4.79915
6.69533 6.20378
6
7.15296 4.08328
6.50827 2.69466
5.91219 3.86661
5.29853 4.16097
6.10838 3.46039
6.34060 2.41599
0
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值