一些参考 http://acm.lilingfei.com/uva-11134-fabled-rooks-%E4%BE%8B%E9%A2%988-4_67
http://blog.csdn.net/shuangde800/article/details/8653730
行和列无关的意思是,本题可以拆成两个完全独立的子问题,分别是行和列的问题,而且这两个问题本质相同,互不影响,只要两个问题都有解,总问题就有解,反之无解。
子问题是关于区间的贪心。
每次选择最早结束的区间来访,且从此区间的最左边开始往右放。最早结束是为了防止抢后面区间的位子,先满足最借据的,再让不借据的迁就借据的。且每次用最小的代价满足你。
#include<bits/stdc++.h>
using namespace std;
struct qj
{
int l,r;
int id;
qj(int a=0,int b=0,int c=0):l(a),r(b),id(c){}
bool operator < (const qj& rhs) const
{
if(r!=rhs.r) return r<rhs.r;
else return l<rhs.l;
}
};
qj QJ[2][5010];
int vis[2][5010];
int wei[2][5010];
int n;
int main()
{
while(scanf("%d",&n),n)
{
memset(vis,0,sizeof(vis));
bool con=false;
int a,b,c,d;
for(int i=1;i<=n;i++)
{
scanf("%d %d %d %d",&a,&b,&c,&d);;
QJ[0][i]=qj(a,c,i);
QJ[1][i]=qj(b,d,i);
}
sort(QJ[0]+1,QJ[0]+1+n);
sort(QJ[1]+1,QJ[1]+1+n);
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++)
{
int k=QJ[i][j].l;
while(vis[i][k]&&k<=QJ[i][j].r) k++;
if(k>QJ[i][j].r)
{
puts("IMPOSSIBLE");
con=true;
}
else
{
vis[i][k]=QJ[i][j].id;
wei[i][QJ[i][j].id]=k;
}
}
if(con) continue;
for(int i=1;i<=n;i++)
printf("%d %d\n",wei[0][i],wei[1][i]);
}
return 0;
}