#include<bits/stdc++.h> #define debu using namespace std; const int maxn=5*1e3+50; struct point { int l,r,id; }; int n,v[maxn]; point a[maxn],b[maxn]; int ansx[maxn],ansy[maxn]; int cmp(point a,point b) { if(a.r==b.r) return a.l<b.l; else return a.r<b.r; } int solve() { sort(a,a+n,cmp); sort(b,b+n,cmp); memset(v,0,sizeof(v)); for(int i=0; i<n; i++) { int flag=0; for(int j=a[i].l; j<=a[i].r; j++) { if(!v[j]) { v[j]=1; ansx[a[i].id]=j; flag=1; break; } } if(!flag) return 0; } memset(v,0,sizeof(v)); for(int i=0; i<n; i++) { int flag=0; for(int j=b[i].l; j<=b[i].r; j++) { if(!v[j]) { v[j]=1; ansy[b[i].id]=j; flag=1; break; } } if(!flag) return 0; } return 1; } void output() { for(int i=0; i<n; i++) printf("%d %d\n",ansx[i],ansy[i]); } int main() { #ifdef debug freopen("in.in","r",stdin); #endif // debug while(scanf("%d",&n)==1&&n) { for(int i=0; i<n; i++) { int x,y,c,d; scanf("%d%d%d%d",&x,&y,&c,&d); a[i].l=x;a[i].r=c;a[i].id=i; b[i].l=y;b[i].r=d;b[i].id=i; } if(solve()) output(); else printf("IMPOSSIBLE\n"); } return 0; }
题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2075
题解:注意到行和列是无关的,行的位置并不会影响列。所以问题变为两个一维问题:在区间[1,n]内选择n个数,使得第i个数在区间[x1i,x2i]内(行,列同)。将每个区间按照右端点从小到大排序(对于选择的每个i,尽可能的不影响下一个区间选择(右端点最小)),在可行区间内,选择未选择的最小值即可。若按左端点,反例[1,1],[1,3],[2,2]。