计算几何初步—【JSOI2015】投影面积

来源:互联网 发布:手机淘宝能删除好评吗? 编辑:程序博客网 时间:2024/05/19 12:28

时限:

1s

Description这里写图片描述

Input

这里写图片描述

Output

这里写图片描述

Sample Input

输入1:
0 90 100
-20 10 20 10

输入2:
1 120 15
-5 5 0 5 0
-20 10 20 10

输入3:
2 150.0000 1000.0000
-60 165 50 165 0
110 25 130 120 1
-205 360 275 360

#

输出1:
0.5000

输出2:
0.3090

输出3:
0.7443

样例3解释:
这里写图片描述

Data Constraint

这里写图片描述

题解:

把整束光拆成若干条光线,模拟每条光线的路径,求出它们照到屏幕上的哪里,如果屏幕上有一部分被光线密集的覆盖,我们就认为光能照到这一篇区域。

有多密呢?注意答案的要求,我们可以设定为屏幕长度×10^-4。

那要拆多少条呢。用一个技巧,能拆多少拆多少,可惜的是,这道题这样子不会过。

我们可以先拆数量较少的光线,如果两条相邻的光线照在屏幕上的位置不连续,则说明它们中间有改变,再把它们中间拆多几条光线,就可以通过此题。

其实说了这么多技巧都是没有用的,重在卡。

#include<cmath>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define LLd long double#define PI 3.1415926535897932384626433#define abs(a) ((a) > 0 ? (a) : -(a))#define fo(i, x, y) for(int i = x; i <= y; i ++)#define hu(a) (a * PI / 180)#define inn(a, b, c) ((a >= b && a <= c) || (a >= c && a <= b))using namespace std;struct pi {    LLd x, y;    pi(){}    pi(LLd x_, LLd y_){x = x_, y = y_;}};struct ld {    pi p, v;    ld(){}    ld(pi p_, pi v_){p = p_, v = v_;}};pi operator +(pi a, pi b) {return pi(a.x + b.x, a.y + b.y);}pi operator -(pi a, pi b) {return pi(a.x - b.x, a.y - b.y);}pi operator *(pi a, LLd b) {return pi(a.x * b, a.y * b);}LLd operator ^(pi a, pi b) {return a.x * b.y - a.y * b.x;}pi operator *(pi a, pi b) {return pi(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);}LLd dot(pi a, pi b) {return a.x * b.x + a.y * b.y;}LLd len(pi a) {return sqrt(dot(a, a));}pi adjust(pi a, LLd b) {return a * (b / len(a));}LLd shade(pi a, pi b) {return dot(a, b) / len(b);}pi pen(pi a) {return pi(a.y, -a.x);}LLd dist(pi a, pi b) {return len(a - b);}LLd distl(ld a, pi b) {abs((b - a.p) ^ a.v) / len(a.v);}pi intersect(ld a, ld b) {return b.p + b.v * ((a.v ^ (a.p - b.p)) / (a.v ^ b.v));}ld translate(ld a, LLd b) {return ld(a.p + adjust(pen(a.v), b), a.v);}pi mirror(ld a, pi b) {return intersect(ld(b, pen(a.v)), a) * 2 - b;}ld reflect(ld a, ld b) {    pi c = intersect(a, b);    pi d = mirror(ld(c, pen(b.v)), a.p);    return ld(c, d - c);}pi angle(LLd a) {return pi(cos(a), sin(a));}pi rotate(pi a, LLd b) {return a * angle(b);}const LLd wu = 0.00000001;int n, tot, last, now, bx[12];LLd x, y, l, r, ang, lnn, d[1000005];ld a[12];bool pd(ld a, ld b) {    if(a.v.x == 0 && b.v.x == 0) return 1;    if(a.v.x == 0 || b.v.x == 0) return 0;    return a.v.y / a.v.x == b.v.y / b.v.x;}bool inl(ld a, pi b) {    return inn(b.x, a.p.x, a.p.x + a.v.x) && inn(b.y, a.p.y, a.p.y + a.v.y);}void Init() {    scanf("%d %Lf %Lf", &n, &ang, &lnn);    n ++;    fo(i, 1, n) {        scanf("%Lf %Lf %Lf %Lf %d", &x, &y, &l, &r, &bx[i]);        a[i] = ld(pi(x, y), pi(l - x, r - y));    }}void Work(ld st) {    int bz = 0; LLd mi = 0, sum = 0;    do {        bz = 0;        fo(i, 1, n) {            if(pd(a[i], st)) continue;            pi b = intersect(st, a[i]);            if((abs(st.v.x) > wu  && (b.x - st.p.x) / st.v.x <= wu) || (abs(st.v.y) < wu && (b.y - st.p.y) / st.v.y <= wu)) continue;            if(!inl(a[i], b)) continue;            LLd f = dist(b, st.p);            if(f + sum > lnn) continue;            if(bz == 0 || f < mi)                bz = i, mi = f;        };        if(bz == 0) continue;        sum += mi;        if(bz == n) {            now = 1;            pi b = intersect(st, a[bz]);            d[++ tot] = b.x;            return;        }        if(bx[bz] == 0) return;        st = reflect(st, a[bz]);    } while(bz);}void Uta() {    ld st = ld(pi(0, 0), pi(0, 1));    st.v = rotate(st.v, hu(- ang / 2));    int g1 = 110000, g2 = g1 * 20;    last = now = 0;    fo(i, 0, g1) {        now = 0;        Work(st);        if(last != now) {            st.v = rotate(st.v, hu(-ang / g1));            fo(j, 1, 20) st.v = rotate(st.v, hu(ang / g2)), Work(st);        }        last = now;        st.v = rotate(st.v, hu(ang / g1));    }}void End() {    sort(d + 1, d + tot + 1);    LLd sum = 0; int last = 1;    fo(i, 2, tot)        if(d[i] - d[i - 1] > a[n].v.x / 3000) sum += d[i - 1] - d[last], last = i;    sum += d[tot] - d[last];    printf("%.4Lf\n", sum / a[n].v.x);}int main() {    freopen("light.in", "r", stdin);    freopen("light.out", "w", stdout);    Init();    Uta();    End();}
1 0