0w1

UVA 11134 Fabled Rooks ( 二維置點問題 )

UVa Online Judge
和這題是一樣的算法:
h0rnet.hatenablog.com
即使變二維,可以將水平座標和鉛直座標做拆解成為兩個相互獨立的置點問題。比較雷的是我忘記判斷優先佇列是空的時候,代表這個位置不能放任何東西,需要跳過,就吃了RE。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e3 + 3;

int n;

struct Rook{
    int id, l, r;
    bool operator < (const Rook &oth) const{
        return r > oth.r;
    } // pq pops least r
} rook[2][MAXN];

bool cmp_l(const Rook &a, const Rook &b){
    return a.l < b.l;
}

int ans[2][MAXN];

void solve(){
    bool fail = false;
    for(int k = 0; k < 2; ++k){
        sort( rook[ k ], rook[ k ] + n, cmp_l );
        priority_queue<Rook> pq;
        int cnt = 0;
        for(int i = 1; i <= n; ++i){
            while( cnt < n && rook[ k ][ cnt ].l <= i )
                pq.push( rook[ k ][ cnt++ ] );
            if( pq.empty() ) continue; // !!
            Rook c = pq.top(); pq.pop();
            if( c.r < i ){ fail = true; break; }
            ans[ k ][ c.id ] = i;
        }
        if( fail || cnt < n || !pq.empty() ){
            puts("IMPOSSIBLE");
            return;
        }
    }
    for(int i = 0; i < n; ++i)
        printf("%d %d\n", ans[0][i], ans[1][i]);
}

int main(){
    while( scanf("%d", &n) == 1 && n ){
        for(int i = 0; i < n; ++i){
            scanf("%d%d%d%d", &rook[0][i].l, &rook[1][i].l, &rook[0][i].r, &rook[1][i].r);
            rook[0][i].id = rook[1][i].id = i;
        }
        solve();
    }
    return 0;
}

我以前是用另一種寫法,現在覺得沒那麼泛用。以右界排序,相同時以長度排序( 右界越小越早消失,越短越需要把握,需要優先進行 )過後,對於每個點,從它的左界到右界掃描過去,放入第一個還沒被佔用的位置。現在想想,應該可以構造測資讓這個時間複雜度很慘。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5000 + 5;

int n;
struct Car{
    int d1, d2, idx;
    bool operator < (const Car &b) const{
        if( d2 != b.d2 ) return d2 < b.d2;
        return d1 > b.d1;
    }   
}cx[MAXN], cy[MAXN];

bool visx[MAXN], visy[MAXN];
int ax[MAXN], ay[MAXN];
bool solve(){
    memset( visx, false, sizeof(visx) );
    memset( visy, false, sizeof(visy) );
    for(int i = 0; i < n; ++i){
        int dx, dy;
        for(dx = cx[i].d1; dx <= cx[i].d2; ++dx)
            if( !visx[dx] ) break;
        if( dx > cx[i].d2 ) return false;
        for(dy = cy[i].d1; dy <= cy[i].d2; ++dy)
            if( !visy[dy] ) break;
        if( dy > cy[i].d2 ) return false;
        visx[dx] = visy[dy] = true;
        int idx = cx[i].idx, idy = cy[i].idx;
        ax[ idx ] = dx, ay[ idy ] = dy;
    }
    return true;
}

int main(){
    ios::sync_with_stdio(false);
    while( cin >> n && n ){
        for(int i = 0; i < n; ++i){
            cin >> cx[i].d1 >> cy[i].d1 >> cx[i].d2 >> cy[i].d2;
            cx[i].idx = cy[i].idx = i;
        }

        sort( cx, cx + n );
        sort( cy, cy + n );

        if( !solve() ) cout << "IMPOSSIBLE" << endl;
        else for(int i = 0; i < n; ++i)
                cout << ax[i] << ' ' << ay[i] << endl;
    }
    return 0;
}