1940:Polygon Programming with Ease

keyword

平面幾何 二分探索 C++

概要

1939:Diplomatic Licenseの入出力を逆にした問題。
普通にやると連立1次方程式を解くことになる。係数行列が複雑でないので多分普通に解けるけど、面倒なので2分探索で解く。nが奇数なので、1ヶ所固定して1周した後戻ってくるとき、真の解より大きい(小さい)値から始めると最初に固定した点より小さい(大きい)値になってしまう。この単調性から2分探索が効く。

int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        vector<double> xs(n),ys(n);
        double x, y;
        for(int i=0; i<n; i++){
            scanf("%lf%lf",&xs[i],&ys[i]);
        }
        double low = -1e13, high = 1e13, mid, tmp;
        for(int loop=0; loop<100; loop++){
            mid = (high+low)*0.5;
            tmp = mid;
            for(int i=0; i<n; i++){
                tmp = 2*xs[i]-tmp;
            }
            if(tmp < mid){
                high = mid;
            }
            else{
                low = mid;
            }
        }
        x = mid;
        low = -1e13, high = 1e13;
        for(int loop=0; loop<100; loop++){
            mid = (high+low)*0.5;
            tmp = mid;
            for(int i=0; i<n; i++){
                tmp = 2*ys[i]-tmp;
            }
            if(tmp < mid){
                high = mid;
            }
            else{
                low = mid;
            }
        }
        y = mid;

        printf("%d ",n);
        for(int i=0; i<n; i++){
            printf("%.6f %.6f%c",x+EPS,y+EPS,(i==n-1)?'\n':' ');
            x = 2*xs[i]-x;
            y = 2*ys[i]-y;
        }
    }

    return 0;
}