UVALive 7345 J - The Hypnotic Spirals

来源:互联网 发布:美工设计经理岗位职责 编辑:程序博客网 时间:2024/04/30 00:47

题目描述:

Professor Parinita Pratim Das, a brilliant
Mathematician of this era, dreams of winning
the Fields Medal someday for her
patented Spirals that are custom made to
hypnotize Engineers. To show that her
ideas actually work she wants to paint her
office room walls with various shapes of
spirals.
Her method of drawing spirals goes
something like this:
• She picks a spiral (in polar coordinates)
of the form, r = aθ
• Then she adds n rays shooting out
from the origin — the i-th ray being
of the form θ = bi (positive or
counter clockwise angle with the x
axis)
• Finally she marks out m points
(rj , θj ) — if a point is in a bounded
region then that entire region will be painted black

Professor Das computes r in meters and knows that she needs 1 liter of black paint for per 10 meter2
area on the wall. She needs your help to calculate how much paint she needs to buy.
Input
The input for this problem starts with S (S ≤ 100), the number of spirals Professor Das wants to paint.
Each of the hypnotic spirals is described in three lines. The first line of a spiral’s description gives
a floating point number giving the value of a (0 < a < 10).
The next line starts with the value of integer n (0 ≤ n ≤ 10). Then follows n floating-point number
θi
, 0 ≤ θi < 2π, each giving the θ values for the n rays. You can assume that all the θi values are
unique (Differs by at least 0.01).
The last line of spiral’s description start with the value of m (0 ≤ m ≤ 1000). The next m pairs
of floating-point numbers, (rj, θj ), 0 < rj < 100, 0 ≤ θj < 2π, in the line gives the coordinates of the
points which Professor Das mark out for painting. You can assume that none of the points will be on
the spiral’s curve or on any of the rays. Note that all the θ values in the input will be given in radians.
Output
For each test case print the spiral’s number (in the format shown in the sample output). Then print the
amount of black paint (in liters, rounded to 4 digits after the decimal point) needed to paint that spiral
on Professor Das’ wall. If the region to be painted is unbounded, print a ‘-1’ instead. The amount of
black paint will be such that an error of 5 × 10−8 will not change the printed output.

题解:

大致思路一下就有, 就是算出来th属于的上一个k和下一个k,然后再看弧度在哪两个射线之间. 但是有细节要注意:
1.看弧度在哪两个之间,涉及到转一圈的问题,我们设置一个-角度(代码中没设但是特判了)和一个大于2*Pi的角度,这样好找,然后k就能统一找了.
2.我们需要用mp来判重复,但是记者一个负角度和一个大于2*Pi的是一样的,需要特殊处理
3.本题中的特殊情况:(1)在第一圈并且有附角的时候,负角度没用,我们应该从0开始积分(2)在最内一圈,不用减去里面的圈,因为没有.(3)在最内一圈和外面一圈的交界处,有的用减去里面的圈,有的不用,分段计算. 总结起来就是,最内圈先是从0开始,并且本身不是环状,影响了这三个

重点:

计算几何的简单题,要有(1)技巧(2)特殊情况的考虑

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <map>#include <algorithm>using namespace std;const int maxn = 1000 + 10;const double Pi = acos(-1.0);double alp[maxn], r, th, a;int alpn, n;map<int, map<int, int> > mp; double f(double aa, double bb) {    return a * a / 6 * (bb * bb * bb - aa * aa * aa);}int getk(double r, double th) {    //printf("222 %f %f %f\n", r, th, a);    int low = 0, high = 1e9;    while(low  <=  high) {        int mid = (low + high) / 2;        if(a * (th + mid * 2 * Pi) > r)            high = mid - 1;        else            low = mid + 1;    }    if(a * (th + low * 2 * Pi) <= r)        while(1);    /* for(int i = 0; ;i++) {        printf("333  %f\n", a * (th + i * 2 * Pi));        if(a * (th + i * 2 * Pi) > r) {            printf("111  %lf\n",  i - 1);            return i - 1;        }        }*/    //    printf("****  %f\n", high - 1);    return high;}void solve() {    mp.clear();    double ans = 0;    scanf("%d", &alpn);    for(int i = 0; i < alpn; i++) {        scanf("%lf", &alp[i]);    }    if(alpn == 0) {        scanf("%d", &n);        for(int i = 0; i < n; i++) {            double a, b;            scanf("%lf%lf", &a, &b);        }        printf("-1\n");        return ;    }    sort(alp, alp + alpn);    alp[alpn] = alp[0] + 2 * Pi;    alpn++;    scanf("%d", &n);    for(int i = 0; i < n; i++) {        scanf("%lf %lf", &r, &th);        int key;        for(int j = 0;;j++) {            if(alp[j] > th) {                key = j;                break;            }        }        double a1, a2;        a2 = alp[key];        if(key != 0)            a1 = alp[key - 1];        else {            a1 = alp[alpn - 2] - 2 * Pi;            //printf("adfdsfs\n");            // swap(a1, a2);        }        //            a2 = alp[alpn - 2] - 2 * Pi;        int k = getk(r, th);        //printf("111   %d\n", k);        if(key == alpn - 1) {            k++;            key = 0;            a1 -= 2 * Pi;            a2 -= 2 * Pi;        }        if(mp[key][k])            continue;        else {            mp[key][k] = 1;            if(k == -1 && a1 < 0) {                ans += f(0, a2);                //printf("fadsfasd");            }            else {                if(k == -1) {                       ans += f(a1 + (k + 1) * 2 * Pi, a2 + (k + 1) * 2 * Pi);                }                else {                    if(k == 0 && a1 < 0) {                        ans += f((k + 1) * 2 * Pi, a2 + (k + 1) * 2 * Pi);                        ans -= f(k * 2 * Pi, a2 + k * 2 * Pi);                        ans += f(a1 + (k + 1) * 2 * Pi, (k + 1) * 2 * Pi);                    }                    else {                        ans += f(a1 + (k + 1) * 2 * Pi, a2 + (k + 1) * 2 * Pi);                        ans -= f(a1 + k * 2 * Pi, a2 + k * 2 * Pi);                    }                }            }        }    }    printf("%.4f liters\n", ans/10);}int main() {    //freopen("j.txt", "r", stdin);    int ncase;    scanf("%d", &ncase);    for(int _ = 1; _ <= ncase; _++) {        printf("Spiral %d: ", _);        scanf("%lf", &a);        solve();    }    return 0;}
0 0
原创粉丝点击