UVA 11134 - Fabled Rooks(经典贪心)
题目链接 https://cn.vjudge.net/problem/UVA-11134
【题意】
你的任务是在n×n的棋盘上放置n辆车,使得任意两辆车不互相攻击,且第i辆车在一个给定的矩形Ri以内。
【输入格式】
多组输入。第一行为整数n(1<=n<=5000),以下n行每行4个整数xli,yli,xri,yri(1<=xli<=xri<=n,1<=yli<=yri<=n)描述一个矩形,其中(xli,xri)是左上角坐标,(xri,yri)是右下角坐标。第i个车的位置必须满足xli<=x<=xri,yli<=y<=yri,输入结束标志为n=0
【输出格式】
无解输出”IMPOSSIBLE”,否则依次按照输入顺序输出n个车的坐标,输出任意解即可。
【思路】
首先行列可以分开考虑,它们互不影响,单单考虑行的话,其实就是给定若干个区间,然后给每个区间都分配一个点,使得点不重复的情况下都能落在相应区间中,可以对区间按右端点升序排序,右端点相等时按左端点升序排序,从左往右看每个区间,尽量往区间的左端点分配即可.
#include<bits/stdc++.h>
using namespace std;
const int maxn=5050;
struct node{
int id,le,ri;
node(int i,int l,int r):id(i),le(l),ri(r){}
bool operator<(const node& e)const{
if(ri==e.ri) return le<e.le;
return ri<e.ri;
}
};
int n;
vector<node>x,y;
bool used[maxn];
int ansx[maxn],ansy[maxn];
int main(){
while(scanf("%d",&n)==1 && n){
x.clear();
y.clear();
for(int i=0;i<n;++i){
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x.push_back(node(i,x1,x2));
y.push_back(node(i,y1,y2));
}
bool ok=1;
sort(x.begin(),x.end());
memset(used,0,sizeof(used));
for(int i=0;i<x.size();++i){
bool flag=0;
for(int j=x[i].le;j<=x[i].ri;++j){
if(!used[j]){
flag=1;
used[j]=1;
ansx[x[i].id]=j;
break;
}
}
if(!flag){ ok=0;break; }
}
if(ok){
sort(y.begin(),y.end());
memset(used,0,sizeof(used));
for(int i=0;i<y.size();++i){
bool flag=0;
for(int j=y[i].le;j<=y[i].ri;++j){
if(!used[j]){
flag=1;
used[j]=1;
ansy[y[i].id]=j;
break;
}
}
if(!flag){ ok=0;break; }
}
}
if(!ok) puts("IMPOSSIBLE");
else for(int i=0;i<n;++i){ printf("%d %d\n",ansx[i],ansy[i]); }
}
return 0;
}