容易发现,行与列是相互独立的,可以单独考虑 。
看到白书上提示说是经典问题的变形,还以为是八皇后之类的,于是写了个回溯,果然TLE了。
仔细考虑后,可以对所有的区间[L,R]按某个顺序排好后,直接将1,2.....n填入每个区间即可。
怎样去排序呢,可能想到L小的要排前,L相同按R小的排前,因为将最小的数字填入 排好序后的第一个区间 不会使结果变糟。 可是这种贪心策略是正确的吗? 很可惜,这种做法不够严谨。 如:
[1 , 1] [1 , 5] [2 , 2] [4 , 4 ] [5 , 5] 这个排序时错误的,正确的是[1 , 1] [2 , 2] [1 , 5] [4 , 4 ] [5 , 5]
前面的推导出了什么问题呢? 只能保证填入的第一个数是正确的。
怎么改正呢,填入第一个数后,将该区间[1 ,1 ]删除 ,将[1 , 5]改为[2 , 5] (因为现在1已经没有作用了),按相同策略重复上面过程即可。
注意 区间的顺序可以用优先队列来维护,不用每次都排一次序。。。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=5050;
struct Range{
int l,r,id;
bool operator < (const Range &b) const {
return (l>b.l || (l==b.l && r>b.r));
}
}xran[maxn],yran[maxn];
int n,ans[maxn][2];
bool check(Range* range , int type){
priority_queue<Range>Q;
for(int i=0;i<n;i++) Q.push(range[i]);
int now = 1;
while(!Q.empty()){
Range tmp = Q.top(); Q.pop();
if(tmp.r < now || tmp.l > now) return false;
if(tmp.l < now) {
tmp.l = now , Q.push(tmp);
continue;
}
ans[tmp.id][type] = now++;
}
return true;
}
int main(){
while(scanf("%d",&n)!=EOF && n){
for(int i=0;i<n;i++){
scanf("%d%d%d%d",&xran[i].l,&yran[i].l,&xran[i].r,&yran[i].r);
xran[i].id = yran[i].id = i;
}
if(check(xran,0) && check(yran,1)) {
for(int i=0;i<n;i++){
printf("%d %d\n",ans[i][0],ans[i][1]);
}
}
else {
puts("IMPOSSIBLE");
}
}
return 0;
}