AOJ 1298 - Separate Points

ミナリンスキー和.

解法

n>=mとして一般性を失わない.(必要なのは白か黒かという区別だけである.)
(1) n=1のとき
m=1である.点は重ならないといっているので,適当な直線で分けられる.

(2) n=2のとき
m=1ならば,黒の2頂点を結ぶ線分内に白い点が入っていないときのみ,分けることができる.
m=2ならば,白黒それぞれの2頂点を結ぶ線分が交点をもたないときのみ,分けることができる.

(3) n>=3のとき
黒い点の凸包を求め,白い点がその凸包に含まれているかどうか調べる.
1点でも含まれていれば,分けることはできない.
同様に白い点に対して,凸包をとり,黒い点がそれに含まれているか調べる.

コード

ライブラリ部分は省略しています.

#include <cstdio>
#include <vector>
#include <algorithm>

typedef long long ll;

int N, M;
std::vector<P> bs, ws;

int main(){
    while(scanf("%d %d", &N, &M), N || M){
        bs.resize(N);
        ws.resize(M);
        
        for(int i=0;i<N;i++){
            ll x, y;
            scanf("%lld %lld", &x, &y);

            bs[i].real(x);
            bs[i].imag(y);
        }
        for(int i=0;i<M;i++){
            ll x, y;
            scanf("%lld %lld", &x, &y);

            ws[i].real(x);
            ws[i].imag(y);        
        }

        if(N == 1 && M == 1){
            puts("YES");
            continue;
        }

        if(N < M){std::swap(bs, ws); std::swap(N, M);}

        if(N == 2){
            if(M == 1){
                puts(ccw(bs[0], bs[1], ws[0]) ? "YES" : "NO");
                continue;
            }else{
                puts(!areIntersectedLines(bs[0], bs[1], ws[0], ws[1]) ? "YES" : "NO");
                continue;
            }
        }
        
        std::vector<P> ch = convex_hull(bs);

        bool res = true;
        for(int i=0;i<M;i++){
            if(isIn(ws[i], ch)){res = false; break;}
        }

        if(M >= 3){
            ch = convex_hull(ws);

            for(int i=0;i<N;i++){
                if(isIn(bs[i], ch)){res = false; break;}
            }
        }

        puts(res ? "YES" : "NO");
    }
}