UVA 11134(p237)----Fabled Rooks

#include<bits/stdc++.h>
#define debu
using  namespace std;
const int maxn=5*1e3+50;
struct point
{
    int l,r,id;
};
int n,v[maxn];
point a[maxn],b[maxn];
int ansx[maxn],ansy[maxn];
int cmp(point a,point b)
{
    if(a.r==b.r) return a.l<b.l;
    else return a.r<b.r;
}
int  solve()
{
    sort(a,a+n,cmp);
    sort(b,b+n,cmp);
    memset(v,0,sizeof(v));
    for(int i=0; i<n; i++)
    {
        int flag=0;
        for(int j=a[i].l; j<=a[i].r; j++)
        {
            if(!v[j])
            {
                v[j]=1;
                ansx[a[i].id]=j;
                flag=1;
                break;
            }
        }
        if(!flag) return 0;
    }
    memset(v,0,sizeof(v));
    for(int i=0; i<n; i++)
    {
        int flag=0;
        for(int j=b[i].l; j<=b[i].r; j++)
        {
            if(!v[j])
            {
                v[j]=1;
                ansy[b[i].id]=j;
                flag=1;
                break;
            }
        }
        if(!flag) return 0;
    }
    return 1;
}
void output()
{
    for(int i=0; i<n; i++)
        printf("%d %d\n",ansx[i],ansy[i]);
}
int main()
{
#ifdef debug
    freopen("in.in","r",stdin);
#endif // debug
    while(scanf("%d",&n)==1&&n)
    {
        for(int i=0; i<n; i++)
        {
            int x,y,c,d;
            scanf("%d%d%d%d",&x,&y,&c,&d);
            a[i].l=x;a[i].r=c;a[i].id=i;
            b[i].l=y;b[i].r=d;b[i].id=i;
        }
        if(solve()) output();
        else printf("IMPOSSIBLE\n");
    }
    return 0;
}

题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2075

题解:注意到行和列是无关的,行的位置并不会影响列。所以问题变为两个一维问题:在区间[1,n]内选择n个数,使得第i个数在区间[x1i,x2i]内(行,列同)。将每个区间按照右端点从小到大排序(对于选择的每个i,尽可能的不影响下一个区间选择(右端点最小)),在可行区间内,选择未选择的最小值即可。若按左端点,反例[1,1],[1,3],[2,2]。

你可能感兴趣的:(UVA 11134(p237)----Fabled Rooks)