2012-09-22 21:22:39Morris

[ZJ][二分+凸包計算面積] b221. 6. 耕者有其田

內容 :

在一個遙遠國度的國王有一塊形狀為凸多邊形的 田地,長年以來由兩個辛勤的農夫幫忙整地施肥與耕種。這凸多邊形的任兩個頂點所連成的線段一定落於此多邊形之內。由於農夫的努力,此田地的收益帶給了國家 許多的財富。為了感謝農夫對王國的貢獻,國王決定將此田地依其面積平均送給這兩個農夫,並把這個任務交由程式設計師來幫忙實現。

程式設計師在此田地的每個頂點依據xy平面實數直角座標系標示了座標。已知所有的頂點都落在x>0的平面上。程式設計師想找出一條通過原點的直線 y=ax (a是一實數係數),使這直線剛好等分劃過這塊農地。

輸入說明 :

輸入檔中所包含之測詴資料的第一行是在測詴資 料裡所列出落在該凸多邊形邊上之點(包含頂點)的個數(N ≤100),接下來則是這N個點的座標資料。每一行有兩個整數表示一個點的 x、y 座標 (x、y的絕對值均小於一百萬),且以一個以上(含一個)的空格分開。在輸入檔中的點座標資料並不一定照順時鐘方向列出。

範例一:

 

範例二:

 

輸出說明 :

針對所輸入的每組測詴資料,每行輸出對應的實數係數a 的值。精確度到小數點後第四位 (第五位以下四捨五入)。誤差在±0.0001之內都算正確。

 

範例輸入 :

輸入範例 一:
3
1 3
3 1
4 4
輸入範例 二:
5
4 4
4 2
2 5
3 -1
1 3

範例輸出 :

輸出範例 一: 
1.0000
輸出範例 二: 
0.9367

提示 :

出處 :

97全國資訊學科能力競賽


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define eps 1e-6
typedef struct {
    double x, y;
} Pt;
Pt P[500], H[500];
int cmp(const void *i, const void *j) {
    static Pt *a, *b;
    a = (Pt *)i, b = (Pt *)j;
    if(a->x != b->x)
        return a->x < b->x;
    return a->y < b->y;
}
double cross(Pt o, Pt a, Pt b) {
    return (a.x - o.x)*(b.y - o.y) -
            (a.y - o.y)*(b.x - o.x);
}
double calc_area(int n, Pt P[]) {
    static int i;
    double sum = 0;
    for(i = 0; i < n-1; i++)
        sum += P[i].x*P[i+1].y - P[i].y*P[i+1].x;
    return fabs(sum/2);
}
int convex(int n) {
    qsort(P, n, sizeof(Pt), cmp);
    int i, t, m = 0;
    for(i = 0; i < n; i++) {
        while(m >= 2 && cross(H[m-2], H[m-1], P[i]) <= 0)
            m--;
        H[m++] = P[i];
    }
    for(i = n-1, t = m+1; i >= 0; i--) {
        while(m >= t && cross(H[m-2], H[m-1], P[i]) <= 0)
            m--;
        H[m++] = P[i];
    }
    for(i = 0; i < m; i++)  P[i] = H[i];
    return m;
}
int main() {
    int n, i;
    while(scanf("%d", &n) == 1) {
        for(i = 0; i < n; i++)
            scanf("%lf %lf", &P[i].x, &P[i].y);
        n = convex(n);
        double A = calc_area(n, P);
        double l = 0xfffffff, r = 0, m;
        double x, y;
        A = A*0.5;
        for(i = 0; i < n; i++) {
            m = P[i].y/P[i].x;
            if(m < l)   l = m;
            if(m > r)   r = m;
        }
        while(fabs(l-r) > eps) {
            m = (l+r)*0.5;
            int it = 0, idx = 0;
            Pt pp[2];
            for(i = 0; i < n-1; i++) {
                if(it == 1)
                    H[idx++] = P[i];
                if((m*P[i].x - P[i].y)*(m*P[i+1].x - P[i+1].y) <= 0) {
                    x = (P[i].x*P[i+1].y - P[i].y*P[i+1].x)/
                        (m*(P[i].x - P[i+1].x) - P[i].y + P[i+1].y);
                    y = m*x;
                    if(it < 2) {
                        if(it == 1) {
                            if(fabs(x-pp[0].x) <= eps && fabs(y-pp[0].y) <= eps)
                                continue;
                        }
                        pp[it].x = x, pp[it].y = y;
                        H[idx++] = pp[it];
                        it++;
                    }
                }
            }
            H[idx++] = pp[0];
            double sum = calc_area(idx, H);
            if(fabs(sum-A) <= eps)
                break;
            if(m*H[1].x-H[1].y <= 0) {
                /*puts("left");*/
                if(sum < A)
                    r = m;
                else
                    l = m;
            } else {
                /*puts("right");*/
                if(sum < A)
                    l = m;
                else
                    r = m;
            }
        }
        printf("%.4lf\n", m);
    }
    return 0;
}

xem phim online 2017-10-03 14:51:08

我在摸索我存在的意義