现在的位置: 首页 > 综合 > 正文

lightoj 1358 Fukushima Nuclear Blast

2018年02月21日 ⁄ 综合 ⁄ 共 2415字 ⁄ 字号 评论关闭

lightoj 1358

题目大意:给定平面上的n个点和一个圆心的坐标,每一秒钟圆的半jing增加1,问几秒之后可以这个圆可以覆盖这个多边形的面积的P%.

思路:二分圆的半径,然后求圆覆盖。

const double PI = acos(-1.0);
#define M 5010
class pnt_type {
public:
    double x,y;
};
class state_type {
public:
    double angle;
    double CoverArea;
};

pnt_type pnt[M];
pnt_type center;

int n;
double R;
inline double Area2(pnt_type &a,pnt_type &b,pnt_type &c) {
    return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
}
inline double dot(pnt_type &a,pnt_type &b,pnt_type &c) {
    return (b.x - a.x) * (c.x - a.x) + (b.y - a.y) * (c.y - a.y);
}
inline double dist(pnt_type &a,pnt_type &b) {
    return sqrt((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y));
}

double init() {
    int i;
    double temp,sum;
    for (i=2; i<n; i++) {
        temp = Area2(pnt[1],pnt[i],pnt[i + 1]);
        sum += temp;
    }
    if (sum < 0) reverse(pnt + 1,pnt + n + 1);
    pnt[n + 1] = pnt[1];
    return sum/2;
}

inline bool inCircle(pnt_type &s) {
    return dist(center,s) <= R;
}

bool SameSide(pnt_type a,pnt_type b) {
    if (dist(a,center) > dist(b,center)) swap(a,b);
    return dot(a,b,center) < eps;
}

double ShadomOnCircle(pnt_type a,pnt_type b) {
    double flag = Area2(center,a,b),res = 0;
    if (fabs(flag) < eps) return 0;

    bool ina = inCircle(a),inb = inCircle(b);
    if (ina && inb) {
        res = fabs(Area2(center,a,b)) / 2;
    } else if (!ina && !inb) {
        if (SameSide(a,b)) {
            double theta = acos(dot(center,a,b) / dist(center,a) / dist(center,b));
            res = R * R * theta / 2;
        } else {
            double height = fabs(Area2(center,a,b)) / dist(a,b);
            double theta = acos(dot(center,a,b) / dist(center,a) / dist(center,b));
            if (height >= R) {
                res = R * R * theta / 2;
            } else {
                double _theta = 2 * acos(height / R);
                res = R * R * (theta - _theta) / 2 + R * R * sin(_theta) / 2;
            }
        }
    } else {
        if (!ina && inb) swap(a,b);
        double height = fabs(Area2(center,a,b)) / dist(a,b);
        double temp = dot(a,center,b);
        double theta = acos(dot(center,a,b) / dist(center,a) / dist(center,b)),theta1,theta2;
        if (fabs(temp) < eps) {
            double _theta = acos(height / R);
            res += R * height / 2 * sin(_theta);
            res += R * R / 2 * (theta - _theta);
        } else {
            theta1 = asin(height / R);
            theta2 = asin(height / dist(a,center));
            if (temp > 0) {
                res += dist(center,a) * R / 2 * sin(PI - theta1 - theta2);
                res += R * R / 2 * (theta + theta1 + theta2 - PI);
            } else {
                res += dist(center,a) * R / 2 * sin(theta2 - theta1);
                res += R * R / 2 * (theta - theta2 + theta1);
            }
        }
    }
    if (flag < 0) return -res;
    else return res;
}

double Cover() {
    int i;
    double res = 0;
    for (i=1; i<=n; i++)
        res += ShadomOnCircle(pnt[i],pnt[i + 1]);
    return res;
}
int main() {
    double ans;
    int T;

    scanf("%d",&T);
    for(int tt=1; tt<=T; tt++) {
        double p;
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            scanf("%lf%lf",&pnt[i].x,&pnt[i].y);
        scanf("%lf%lf%lf",¢er.x,¢er.y,&p);
        double totarea=init()*p/100;
        double l=0,r=3000;
        double mid;
        while(l<r-eps) {
            mid=(l+r)/2;
            R=mid;
            if(Cover()>=totarea)r=mid;
            else l=mid;
        }
        printf("Case %d: %.0lf\n",tt,l);
    }
    return 0;
}

套模板的题。还没有过掉。

若是有人过掉了求告知。求科普。

抱歉!评论已关闭.