3069:Saruman's Army

keyword

greedy C++

概要

円の半径Rと数列x_iが与えられる。円の中心をx_iのいずれかに置いて円が全ての点x_iを被覆するようにしたい。置く円の最小個数を求める問題。
x_iをソートして小さい方から順に処理する。x_i+kに円を置いてもx_iが被覆されるならx_iには置かないことにすればよい。

int main(){
    int R, i, j, k, n, ans;
    int xs[1005];
    bool covered[1005];

    while(scanf("%d%d",&R, &n)){
        if(R==-1 && n==-1) break;
        REPONE(i,n) scanf("%d",xs+i);
        REP(i,1005) covered[i] = false;

        xs[0] = -10000;
        xs[n+1] = 10000;
        covered[0] = covered[n+1] = true;
        sort(xs,xs+(n+2));
        ans = 0;
        i = 1;
        while(i<=n){
            for(j=i;xs[i] >= xs[j+1] - R; j++);
            ans++;
            for(k=j;xs[j] >= xs[k+1] - R; k++);
            for(;i<=k;i++)covered[i] = true;
            for(i=1;covered[i];i++);
        }
        printf("%d\n",ans);
    }

    return 0;
}