UVa:11134 Fabled Rooks

非常关键的一点是行和列是独立的,不相互影响。所以判断车是否相互攻击只需要行不相互攻击,列也不相互攻击即可。这样二维可以转化成两个一维。

一维的问题是,在给定的每个区间上选一个点使得该点不再其他区间上出现。贪心,优先给右端点小的线段选点即可。类似于上一个题,我用优先队列做得。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define MOD 20071027
#define MAXN 20005
using namespace std;
struct Segment
{
    int l,r;
    int num,pos;
    Segment(int a=0,int b=0,int c=0):l(a),r(b),num(c) {}
    bool operator < (const Segment &p ) const
    {
        return r>p.r;
    }
};
bool cmp(Segment a,Segment b)
{
    return a.num<b.num;
}
vector<Segment> x[5005],y[5005];
void Init()
{
    for(int i=1; i<=5000; ++i)
    {
        x[i].clear();
        y[i].clear();
    }
}
void process(priority_queue<Segment> &pq,int v,vector<Segment> &ans)
{
    if(!pq.empty())
    {
        Segment s=pq.top();
        pq.pop();
        s.pos=v;
        ans.push_back(s);
    }
}
bool solve(vector<Segment> vec[],vector<Segment> &ans,int minn,int maxn)
{
    priority_queue<Segment> pq;
    for(int i=minn; i<=maxn; ++i)
    {
        if(!pq.empty()&&pq.top().r<i) return false;
        for(int j=0; j<vec[i].size(); ++j)
            pq.push(vec[i][j]);
        process(pq,i,ans);
    }
    if(pq.empty()) return true;
    else return false;
}
int main()
{
    int n;
    while(scanf("%d",&n)&&n)
    {
        Init();
        int a,b,c,d;
        int minx=INF,miny=INF,maxx=0,maxy=0;
        for(int i=0; i<n; ++i)
        {
            scanf("%d%d%d%d",&a,&b,&c,&d);
            x[a].push_back(Segment(a,c,i));
            y[b].push_back(Segment(b,d,i));
            minx=min(minx,a);
            maxx=max(maxx,c);
            miny=min(miny,b);
            maxy=max(maxy,d);
        }
        vector<Segment> ax,ay;
        if(!solve(x,ax,minx,maxx)||!solve(y,ay,miny,maxy)) puts("IMPOSSIBLE");
        else
        {
            sort(ax.begin(),ax.end(),cmp);
            sort(ay.begin(),ay.end(),cmp);
            for(int i=0; i<n; ++i)
                printf("%d %d\n",ax[i].pos,ay[i].pos);
        }
    }
    return 0;
}


 

你可能感兴趣的:(优先队列)