1. 程式人生 > >poj3301--Texas Trip(最小正方形覆蓋)

poj3301--Texas Trip(最小正方形覆蓋)

題目大意:給出n個點的座標,現在要求一個正方形,完全包圍n個點,並且正方形面積最小,求最小的正方形面積。

表示不能理解為什麼面積隨著角度的變化是一個單峰的函式,等待大牛告訴一下,,,

如果面積隨角度變化是單峰的函式,那麼自然就可以想到是三分,按照題目要求求正方形最小的面積,如果正方形是平行於x軸的,那麼正方形面積是x的最大距離*y的最大的距離。然後旋轉正方形,在0到90度內總會找到一個正方形面積的最小值,,,但是旋轉正方形比較麻煩,我們可以考慮旋轉座標系,將做座標系旋轉0到90度,按旋轉的角度重新計算各點的座標,然後找出x的差和y的差,計算面積。

因為是單峰的函式,所以用三分角度,找到一個最小的面積。

注意:三分的eqs要很小,,,,,

角度旋轉公式x = x*cos(j) - y*sin(j) ; y = x*sin(j) + y*cos(j) ;

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std ;
#define eqs 1e-12
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
struct node{
    double x , y ;
}p[35];
int n ;
double maxx , minx , maxy , miny ;
double f(double j) {
    int i ;
    double x , y ;
    maxx = maxy = -INF ;
    minx = miny = INF ;
    for(i = 0 ; i < n ; i++) {
        x = p[i].x*cos(j) - p[i].y*sin(j) ;
        y = p[i].x*sin(j) + p[i].y*cos(j) ;
        maxx = max(maxx,x) ;
        minx = min(minx,x) ;
        maxy = max(maxy,y) ;
        miny = min(miny,y) ;
    }
    return max( maxx-minx,maxy-miny ) ;
}
int main() {
    int t , i ;
    scanf("%d", &t) ;
    while( t-- ) {
        scanf("%d", &n) ;
        for(i = 0 ; i < n ; i++) {
            scanf("%lf %lf", &p[i].x, &p[i].y) ;
        }
        double low = 0.0 , mid1 , mid2 , high = PI/2.0;
        while( low + eqs < high ) {
            mid1 = (low + high)/2.0 ;
            mid2 = (mid1 + high) / 2.0 ;
            if( f(mid1) > f(mid2) )
                low = mid1 ;
            else
                high = mid2 ;
        }
        low = f(low) ;
        printf("%.2lf\n", low*low ) ;
    }
    return 0 ;
}