Fork me on GitHub

UVALive 6092 Catching Shade in Flatland --枚举+几何计算

题意: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

 

当时的代码(考虑了可能包含原点):

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

struct node
{
    double x,y,r;
}p[205];

int getPlane(double nx,double ny)
{
    if(nx > 0 && ny > 0)
        return 1;
    else if(nx > 0 && ny < 0)
        return 2;
    else if(nx < 0 && ny < 0)
        return 3;
    else if(nx < 0 && ny > 0)
        return 4;
    else
        return 1;
}

double dis(int nx,int ny)
{
    return sqrt(nx*nx + ny*ny);
}

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,&p[i].r);
        int S = 24*60;
        double Si = 24.0*60.0;
        int Plane;
        double maxi = 0.0;
        for(i=0;i<S;i++)
        {
            if(i == 0 || i == 360 || i == 720 || i == 1080)
                continue;
            double A = tan(2*pi*(double)i/Si);
            double B = -1.0;
            double k = A;
            double di = sqrt(A*A+B*B);
            if(i > 0 && i < 360)
                Plane = 1;
            else if(i > 360 && i < 720)
                Plane = 2;
            else if(i > 720 && i < 1080)
                Plane = 3;
            else
                Plane = 4;
            double sum = 0.0;
            for(j=0;j<n;j++)
            {
                double x = p[j].x;
                double y = p[j].y;
                double r = p[j].r;
                double PtoL = fabs(A*x-y)/di;
                if(PtoL > r)
                    continue;
                double AA = k*k+1.0;
                double BB = -(2.0*x+2.0*k*y);
                double CC = x*x + y*y - r*r;
                if(BB*BB-4.0*AA*CC <= 0.0)
                    continue;
                double jie1x = (-BB+sqrt(BB*BB-4.0*AA*CC))/(2.0*AA);
                double jie1y = k*jie1x;
                double jie2x = (-BB-sqrt(BB*BB-4.0*AA*CC))/(2.0*AA);
                double jie2y = k*jie2x;
                int P1 = getPlane(jie1x,jie1y);
                int P2 = getPlane(jie2x,jie2y);
                if(P1 == Plane && P2 == Plane)
                    sum += 2.0*sqrt(r*r-PtoL*PtoL);
                else if(P1 == Plane)
                    sum += dis(jie1x,jie1y);
                else if(P2 == Plane)
                    sum += dis(jie2x,jie2y);
            }
            maxi = max(maxi,sum);
        }
        //up
        double sum = 0.0;
        for(j=0;j<n;j++)
        {
            double x = p[j].x;
            double y = p[j].y;
            double r = p[j].r;
            double PtoL = x;
            if(PtoL > r)
                continue;
            double AA = 1.0;
            double BB = -2.0*y;
            double CC = x*x + y*y - r*r;
            double jie1x = 0.0;
            double jie1y = (-BB+sqrt(BB*BB-4.0*AA*CC))/(2.0*AA);
            double jie2x = 0.0;
            double jie2y = (-BB-sqrt(BB*BB-4.0*AA*CC))/(2.0*AA);
            if(jie1y > 0 && jie2y > 0)
                sum += fabs(jie1y-jie2y);
            else if(jie1y > 0)
                sum += jie1y;
            else if(jie2y > 0)
                sum += jie2y;
        }
        maxi = max(maxi,sum);
        //down
        sum = 0.0;
        for(j=0;j<n;j++)
        {
            double x = p[j].x;
            double y = p[j].y;
            double r = p[j].r;
            double PtoL = x;
            if(PtoL > r)
                continue;
            double AA = 1.0;
            double BB = -2.0*y;
            double CC = x*x + y*y - r*r;
            double jie1x = 0.0;
            double jie1y = (-BB+sqrt(BB*BB-4.0*AA*CC))/(2.0*AA);
            double jie2x = 0.0;
            double jie2y = (-BB-sqrt(BB*BB-4.0*AA*CC))/(2.0*AA);
            if(jie1y < 0 && jie2y < 0)
                sum += fabs(jie1y-jie2y);
            else if(jie1y < 0)
                sum += -jie1y;
            else if(jie2y < 0)
                sum += -jie2y;
        }
        maxi = max(maxi,sum);
        //right
        sum = 0.0;
        for(j=0;j<n;j++)
        {
            double x = p[j].x;
            double y = p[j].y;
            double r = p[j].r;
            double PtoL = y;
            if(PtoL > r)
                continue;
            double AA = 1.0;
            double BB = -2.0*x;
            double CC = x*x + y*y - r*r;
            double jie1x = (-BB+sqrt(BB*BB-4.0*AA*CC))/(2.0*AA);
            double jie1y = 0.0;
            double jie2x = (-BB-sqrt(BB*BB-4.0*AA*CC))/(2.0*AA);
            double jie2y = 0.0;
            if(jie1x > 0 && jie2x > 0)
                sum += fabs(jie1x-jie2x);
            else if(jie1x > 0)
                sum += jie1x;
            else if(jie2x > 0)
                sum += jie2x;
        }
        maxi = max(maxi,sum);
        //left
        sum = 0.0;
        for(j=0;j<n;j++)
        {
            double x = p[j].x;
            double y = p[j].y;
            double r = p[j].r;
            double PtoL = y;
            if(PtoL > r)
                continue;
            double AA = 1.0;
            double BB = -2.0*x;
            double CC = x*x + y*y - r*r;
            double jie1x = (-BB+sqrt(BB*BB-4.0*AA*CC))/(2.0*AA);
            double jie1y = 0.0;
            double jie2x = (-BB-sqrt(BB*BB-4.0*AA*CC))/(2.0*AA);
            double jie2y = 0.0;
            if(jie1x < 0 && jie2x < 0)
                sum += fabs(jie1x-jie2x);
            else if(jie1x < 0)
                sum += -jie1x;
            else if(jie2x < 0)
                sum += -jie2x;
        }
        maxi = max(maxi,sum);
        printf("%.3lf\n",maxi);
    }
    return 0;
}
View Code

 

posted @ 2014-08-11 20:23  whatbeg  阅读(547)  评论(0编辑  收藏  举报