题目地址:UVa 11134
这题因为行与列是无关的,互无影响的。所以可以将行或列分开来计算。这就相当于转化成了在期间[1,n]内选择n个不同的整数,使得第i个整数在闭区间[Li,Ri]内。这就转换成了一个贪心问题了。但是注意不能先按照左端点排序,再按右端点排序,然后尽量往左边放,比如,(1,1),(1,3),(2,2),这样是不对的,应该按右端点为主关键字排序,再按左端点为次关键字排序。看到网上的方法全都是用每次选一个数后,都要在后面的区间中删去这个数,还要用到优先队列。。感觉没必要这样做。。只要把排序关键字换换就可以了。
代码如下:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
int a[6000], b[6000], _hash[6000];
struct node
{
int l, r, num;
}x[100000], y[100000];
int cmp(node x, node y)
{
if(x.r==y.r) return x.l<y.l;
return x.r<y.r;
}
int main()
{
int n, i, j, flag, z;
while(scanf("%d",&n)!=EOF&&n)
{
for(i=0;i<n;i++)
{
scanf("%d%d%d%d",&x[i].l,&y[i].l,&x[i].r,&y[i].r);
x[i].num=i;
y[i].num=i;
}
memset(_hash,0,sizeof(_hash));
sort(x,x+n,cmp);
sort(y,y+n,cmp);
z=0;
for(i=0;i<n;i++)
{
flag=0;
for(j=x[i].l;j<=x[i].r;j++)
{
if(!_hash[j])
{
a[x[i].num]=j;
_hash[j]=1;
flag=1;
break;
}
}
if(!flag)
{
z=1;
break;
}
}
if(z)
{
printf("IMPOSSIBLE\n");
continue ;
}
memset(_hash,0,sizeof(_hash));
z=0;
for(i=0;i<n;i++)
{
flag=0;
for(j=y[i].l;j<=y[i].r;j++)
{
if(!_hash[j])
{
b[y[i].num]=j;
_hash[j]=1;
flag=1;
break;
}
}
if(!flag)
{
z=1;
break;
}
}
if(z)
{
printf("IMPOSSIBLE\n");
continue ;
}
for(i=0;i<n;i++)
{
printf("%d %d\n",a[i],b[i]);
}
}
return 0;
}