24h購物| | PChome| 登入
2013-04-11 20:43:07| 人氣722| 回應0 | 上一篇 | 下一篇

[UVA][幾何、半平面交] 11265 - The Sultan's Problem

推薦 0 收藏 0 轉貼0 訂閱站台

Problem F
The Sultan’s Problem
Input: Standard Input

Output: Standard Output

 

Once upon a time, there lived a greatsultan, who was very much fond of his wife. He wanted to build a Tajmahal for his wife (ya, oursultan idolized Mughal emperor Shahjahan).But alas, due to budget cuts, loans, dues and many manythings, he had no fund to build something so big. So, he decided to build abeautiful garden, inside his palace.

 

The garden is a rectangular pieceof land. All the palace’s water lines run through the garden, thus, dividing itinto pieces of varying shapes. He wanted to cover each piece of the land withflowers of same kind.

Figure 1

The figure above shows a sampleflower garden. All the lines are straight lines, with two end points on twodifferent edge of the rectangle. Each piece of the garden is covered with thesame kind of flowers.

 

The garden has a small fountain,located at position (x,y).You can assume that, it is not on any of the lines. He wants to fill that piecewith her favourite flower. So, he asks you to findthe area of that piece.

 

Input

 

Input contains around 500 testcases. Each case starts with 5 integers, N, W, H, x,y, the number of lines, width and height of the garden and the locationof the fountain. Next N lines each contain 4 integers, x1y1 x2 y2, the two end points of the line.The end points are always on the boundary of the garden. You can assume that,the fountain is not located on any line.

Output

 

For each test case, output thecase number, with the area of the piece covered with her favouriteflower. Print 3 digits after the decimal point.

 

Constraints

  • 1 ≤ W, H ≤ 200,000
  • 1 ≤ N ≤ 500

 

Sample Input

Sample Output

3 100 100 20 30

0 0 100 100

100 0 0 100

0 40 40 100

 

Case #1: 1780.000

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Problemsetter: Manzurur Rahman Khan

Special Thanks To: Mohammad MahmudurRahman



解題思路:

一個型態 polygon,以及求一條長直線交多邊形的兩交點,
如果有交的話,將這個多邊形一分為二,同時只保留涵蓋花園的那塊多邊形,
最後使用行列式算花園面積



#include <stdio.h>
#include <math.h>
struct Pt {
    double x, y;
};
struct Polygon {
    Pt p[505];
    int n;
};
double calcArea(Polygon &p) {
    static int i;
    double sum = 0;
    p.p[p.n] = p.p[0];
    for(i = 0; i < p.n; i++)
        sum += p.p[i].x*p.p[i+1].y - p.p[i].y*p.p[i+1].x;
    return fabs(sum/2);
}
void print(Polygon &p) {
    for(int i = 0; i < p.n; i++)
        printf("%lf %lf\n", p.p[i].x, p.p[i].y);
    puts("=====");
}
int main() {
    int n, w, h;
    int cases = 0;
    int i, j, k;
    double sx, sy, ex, ey, xi, yi;
    while(scanf("%d %d %d", &n, &w, &h) == 3) {
        scanf("%lf %lf", &xi, &yi);
        Polygon A, B, C;
        A.n = 4;
        A.p[0].x = 0, A.p[0].y = 0;
        A.p[1].x = w, A.p[1].y = 0;
        A.p[2].x = w, A.p[2].y = h;
        A.p[3].x = 0, A.p[3].y = h;
        while(n--) {
            scanf("%lf %lf %lf %lf", &sx, &sy, &ex, &ey);
            // ax + by + c = 0
            double a, b, c;
#define eps 1e-8
            double m = (sy-ey)/(sx-ex);
            if(fabs(sx-ex) < eps)
                a = 1, b = 0, c = -sx;
            else
                a = m, b = -1, c = -(sx*a+b*sy);
            //printf("%lf x + %lf y + %lf = 0\n", a, b, c);
            A.p[A.n] = A.p[0];
            B.n = 0, C.n = 0;
            Pt intP[2];
            int point = 0;
            for(i = 0; i < A.n; i++) {
                if(point == 1) {
                    if(B.n == 0 || fabs(B.p[B.n-1].x-A.p[i].x) > eps ||
                       fabs(B.p[B.n-1].y-A.p[i].y) > eps)
                    B.p[B.n++] = A.p[i];
                } else {
                    if(C.n == 0 || fabs(C.p[C.n-1].x-A.p[i].x) > eps ||
                       fabs(C.p[C.n-1].y-A.p[i].y) > eps)
                    C.p[C.n++] = A.p[i];
                }
                //printf("(%lf %lf)-(%lf %lf)\n", A.p[i].x, A.p[i].y, A.p[i+1].x, A.p[i+1].y);
                if((a*A.p[i].x+b*A.p[i].y+c)*(a*A.p[i+1].x+b*A.p[i+1].y+c) <= eps) {
                    if(point == 2)  continue;
                    double ta, tb, tc;
                    double tm = (A.p[i].y-A.p[i+1].y)/(A.p[i].x-A.p[i+1].x);
                    if(fabs(A.p[i].x-A.p[i+1].x) < eps)
                        ta = 1, tb = 0, tc = -A.p[i].x;
                    else
                        ta = tm, tb = -1, tc = -(A.p[i].x*ta+A.p[i].y*tb);
                    // ax+by+c = 0, ta*x+tb*y+tc = 0
                    //printf("%lf x + %lf y + %lf = 0\n", ta, tb, tc);
                    double rx, ry, r;
                    r = a*tb-ta*b;
                    rx = (-c)*tb-(-tc)*b;
                    ry = a*(-tc)-ta*(-c);
                    rx = rx/r;
                    ry = ry/r;
                    if(fabs(r) < eps)   continue; // no intersection
                    if(point == 1) {
                        if(fabs(rx-intP[0].x) < eps && fabs(ry-intP[0].y) < eps)
                            continue;
                    }
                    //printf("intersection %lf %lf\n", rx, ry);
                    intP[point].x = rx, intP[point].y = ry;
                    if(B.n == 0 || fabs(B.p[B.n-1].x-rx) > eps || fabs(B.p[B.n-1].y-ry) > eps)
                        B.p[B.n++] = intP[point];
                    if(C.n == 0 || fabs(C.p[C.n-1].x-rx) > eps || fabs(C.p[C.n-1].y-ry) > eps)
                        C.p[C.n++] = intP[point];
                    point++;
                }
            }
            if(point != 2)
                continue;
            int f1, f2;
            f1 = (a*B.p[B.n/2].x + b*B.p[B.n/2].y + c) < eps;
            f2 = (a*xi + b*yi + c) < eps;
            //print(B);
            //print(C);
            if(f1 == f2 && point) {// same side
                //puts("B side");
                A = B;
            } else {
                //puts("C side");
                A = C;
            }
            while(fabs(A.p[A.n-1].x-A.p[0].x) < eps &&
               fabs(A.p[A.n-1].y-A.p[0].y) < eps)
                A.n--;
            //print(A);
        }
        printf("Case #%d: %.3lf\n", ++cases, calcArea(A));
    }
    return 0;
}

台長: Morris
人氣(722) | 回應(0)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 不分類 | 個人分類: UVA |
此分類下一篇:[UVA][匈牙利匹配] 670 - The dog task
此分類上一篇:[UVA][生命遊戲] 447 - Population Explosion

是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文