UVA11134 传说中的车 Fabled Rooks

首先,根据数据范围,可以得到这是一题O(N2)

考虑贪心

发现行和列是不相关的,于是可以把他们分成两个一维区间问题,也就是在线段中选出点使得每个线段中都有一个点,求出方案。

先考虑尽量不对后面造成影响,也就是留后路,所以前面要尽量选靠前的,按照右端点排序,分别处理。

最后记得按原序号输出。

#include<bits/stdc++.h>
using namespace std;
int n;
bool b1[5005],b2[5005]; 
struct node{int x1,x2,y1,y2,x,y,ind;}a[5005];
bool cmp(node a,node b){return a.x2<b.x2;}//第一次排序
bool cmp1(node a,node b){return a.y2<b.y2;}//第二次
bool cmp2(node a,node b){return a.ind<b.ind;}//第三次
bool ccf(){//咳咳
    fill(b1,b1+n+1,0);fill(b2,b2+n+1,0);//清零使用数组
    for(int i=1;i<=n;i++){
        scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);//输入
        a[i].ind=i;记录序号
    }
    sort(a+1,a+n+1,cmp);//处理横坐标
    for(int i=1;i<=n;i++){
        int j=a[i].x1;
        for(;j<=a[i].x2;++j)//从前往后找
         if(!b1[j]){b1[j]=1,a[i].x=j;break;}
        if(j>a[i].x2)return false;//如果找不到就返回
    }
    sort(a+1,a+n+1,cmp1);//处理纵坐标
    for(int i=1;i<=n;i++){
        int j=a[i].y1;
        for(;j<=a[i].y2;++j)
         if(!b2[j]){b2[j]=1,a[i].y=j;break;}
        if(j>a[i].y2)return false;
    }
    sort(a+1,a+n+1,cmp2);//按照原序号输出
    for(int i=1;i<=n;i++)
     printf("%d %d\n",a[i].x,a[i].y);
    return true;
}
int main(){
    while(~scanf("%d",&n)&&n)
     if(!ccf())puts("IMPOSSIBLE");
} 

猜你喜欢

转载自www.cnblogs.com/coder-cjh/p/11617059.html