题意:x=[-200,200],y=[-200,200]的平面,一天中太阳从不同角度射到长椅(原点(0,0))上,有一些树(用圆表示),问哪个时刻(分钟为单位)太阳光线与这些圆所交的弦长总和最长。太阳距离原点总是500m。(这些圆不会互相相交,每个圆都不包括原点或者不经过原点

解法:直接暴力24*60分钟,找出此时的角度,然后求出直线方程,再枚举每个圆,求出弦长。注意这里每个圆都不包括原点,所以直线与圆的交点一定在同一侧,所以。。我当时想多了,没看清题目。把他当成可以包含原点了,代码超长,幸好过了。

代码:

没想多应该这样就可以了:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#define INint 2147483647
#define pi acos(-1.0)
#define eps 1e-4
using namespace std;
#define N 100102
#define M 22

typedef struct point
{
    double x,y;
    point(double x=0,double y=0):x(x),y(y){}
}Vector;

double DegtoRad(double deg)
{
    return deg/180.0*pi;
}

int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    return x<0?-1:1;
}
Vector operator  + (Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);}
Vector operator  -  (point A,point B){return Vector(A.x-B.x,A.y-B.y);  }
Vector operator  *  (Vector A,double p){return Vector(A.x*p,A.y*p);}
Vector operator  /  (Vector A,double p){return Vector(A.x/p,A.y/p);}
bool operator ==  (const point& a,const point& b){return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;}
bool operator < (const point& a,const point& b){return a.x<b.x ||(a.x==b.x&&a.y<b.y);}
double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}   //叉积 ,大于零说明B在A的左边。小于零说明B在A的右边
double Dot(Vector A,Vector B){return A.x*B.x+A.y*B.y;}    //点积
double length(Vector A){return sqrt(Dot(A,A));}              //向量长度

double DistanceToSegment(point P,point A,point B)
{
    if(A==B) return length(P-A);
    Vector v1=B-A,v2=P-A,v3=P-B;
    if(dcmp(Dot(v1,v2))<0)  return length(v2);
    else if(dcmp(Dot(v1,v3))>0) return length(v3);
    else return fabs(Cross(v1,v2))/length(v1);
}

point p[205];
double ra[205];

int main()
{
    int n,i,j;
    while(scanf("%d",&n)!=EOF && n)
    {
        for(i=0;i<n;i++)
            scanf("%lf%lf%lf",&p[i].x,&p[i].y,&ra[i]);
        double maxi = 0.0;
        int S = 24*60;
        for(i=0;i<S;i++)
        {
            point A,B,C;
            A = point(0.0,0.0);
            double rad = DegtoRad(i/4.0);
            B = point(500*sin(rad),500*cos(rad));
            double sum = 0.0;
            for(j=0;j<n;j++)
            {
                C = p[j];
                double dis = DistanceToSegment(C,A,B);
                if(dis >= ra[j])
                    continue;
                sum += 2.0*sqrt(ra[j]*ra[j]-dis*dis);
            }
            maxi = max(maxi,sum);
        }
        printf("%.3lf\n",maxi);
    }
    return 0;
}
View Code

相关文章: