2011-07-19 13:03:54Morris

a191. 在世界遙遠的彼方

a191. 在世界遙遠的彼方

內容 :

超遠距離戀愛(Long distance love), 可說是戀愛中必敗的一種形式, 可是卻又是戀人們中最崇尚的一種戀愛

小光是個失敗者, 絕對不能放棄這個失敗的機會, 他挑了一張地圖出來, 希望能找到失敗評估最高的地點來實施他的失敗計畫, 不過地點有很多, 小光是個失敗者, 解決不了這個問題, 只好請你來解決了

你只需要算出每一個地點的失敗評估, 決定哪一個失敗地點, 後面的事情就交給小光了

失敗評估 Li = Max(  ( P.xi - P.xj )( P.xi - P.xj ) + ( P.yi - P.yj )( P.yi - P.yj )  ), Pj S

輸入說明 :

有多組測試資料, 每組第一行有一個正整數 N (1 ≦ N ≦ 1,0000)

接下來有 N 行, 第 i 行上有兩個數字 xi yi  , (0 ≦ xi yi ≦ 3,0000), 代表在地圖上的位置

    

輸出說明 :

對每一個地點, 按照輸入順序, 輸出最高的失敗評估

範例輸入 :

12
2 1
3 1
1 2
2 2
3 2
4 2
1 3
2 3
3 3
4 3
2 4
3 4

範例輸出 :

10
10
10
5
5
10
10
5
5
10
10
10
提示 :
× O(N*N) 不可

出處 :

(管理:morris1028)



作法 : 作凸包, 拿凸包上的點來窮舉, 速度會快很多

我有想過拿最遠點對上的點, 去做窮舉, 而不是凸包上的所有點, 但是我發現了反例
如下圖 :


最遠點對只有一組 : (1, 15) & (20, 9)
那假使要找 (10, 6) 的最遠點, 實際上是 (18, 18)
拿 (1, 15) | (20, 9) 都是錯誤的

我也有想過, 假使凸包上的點是順時針的儲存, 那麼比較距離的話, 查看使否有遞增現象
, 來當作剪枝條件, 但是這個方法失敗了

/**********************************************************************************/
/*  Problem: a191 "在世界遙遠的彼方" from                                 */
/*  Language: C                                                                   */
/*  Result: WA (line:3) on ZeroJudge                                              */
/*  Author: morris1028 at 2011-07-19 12:58:35                                     */
/**********************************************************************************/


#include<stdio.h>
typedef struct Point {
    int x, y, tag;
}Point;
Point P[10000], CH[10000*2], X[10000];
void MergeSort(int, int);
void Merge(int, int, int);
int cross(Point o, Point a, Point b) {
    return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
}
int monotone_chain(int N) {
    MergeSort(0, N-1);
    int m = 0, a, t;
    for(a = 0; a < N; a++) {
        while(m >= 2 && cross(CH[m-2], CH[m-1], P[a]) <= 0)
            m--;
        CH[m++] = P[a];
    }
    for(a = N-2, t = m+1; a >= 0; a--) {
        while(m >= t && cross(CH[m-2], CH[m-1], P[a]) <= 0)
            m--;
        CH[m++] = P[a];
    }
    return m--;
}
main() {
    int N, M, a, b, c;
    while(scanf("%d", &N) == 1) {
        for(a = 0; a < N; a++)
            scanf("%d %d", &P[a].x, &P[a].y), P[a].tag = a;
        M = monotone_chain(N);
        int t, M1, M2;
        for(a = 0; a < N; a++) {
            M1 = M2 = b = 0;
            while(b < M) {
                t = (P[a].x - CH[b].x)*(P[a].x - CH[b].x) +
                (P[a].y - CH[b].y)*(P[a].y - CH[b].y);
                if(M1 <= t)
                    b++, M1 = t;
                else break;
            }
            if(b != M) {
                c = M-1;
                while(c > b) {
                    t = (P[a].x - CH[c].x)*(P[a].x - CH[c].x) +
                    (P[a].y - CH[c].y)*(P[a].y - CH[c].y);
                    if(M2 <= t)
                        c--, M2 = t;
                    else break;
                }
            }
            P[a].y = M1 > M2 ? M1 : M2, P[a].x = P[a].tag;
        }
        MergeSort(0, N-1);
        for(a = 0; a < N; a++) {
            printf("%d\n", P[a].y);
        }
    }
    return 0;
}
void MergeSort(int l, int h) {
    if(l < h) {
        int m = (l+h)/2;
        MergeSort(l, m);
        MergeSort(m+1, h);
        Merge(l, m, h);
    }
}
void Merge(int l, int m, int h) {
    int In1 = l, In2 = m+1;
    int a, b, Top = 0;
    while(In1 <= m && In2 <= h) {
        if(P[In1].x < P[In2].x || (P[In1].x == P[In2].x && P[In1].y < P[In2].y))
            X[Top++] = P[In1++];
        else
            X[Top++] = P[In2++];
    }
    while(In1 <= m) X[Top++] = P[In1++];
    while(In2 <= h)    X[Top++] = P[In2++];
    for(a = 0, b = l; a < Top; a++, b++)
        P[b] = X[a];
}