因为行和列是无关的,所以可以单独处理,将问题分解成两个,那么需要求的就是在这n个区间里任选一个数,且这个数不重复。 这很像之前紫书上将的区间问题,可以采取贪心的策略,将区间(a,b) 先按照b从小到大排,再按照a从小到大排,然后在区间中的还没有被选的数字里优先挑选较小的数字。
但是由于这样经过排序后原来的顺序已经打乱了,所以预先给每个区间分配一个id ,一个v保存选的值,然后再按照id还原顺序就好了。
#include<bits/stdc++.h> using namespace std; const int max_n = 5005; int n,vis_x[max_n],vis_y[max_n],vis[max_n]; struct point_x{ int x1,x2,id,v; }a[max_n]; struct point_y{ int y1,y2,id,v; }b[max_n]; bool cmp(point_x a,point_x b){ return a.x2<b.x2||a.x2==b.x2&&a.x1<b.x1; } bool cmp2(point_y a,point_y b){ return a.y2<b.y2||a.y2==b.y2&&a.y1<b.y1; } bool cmp3(point_x a,point_x b){ return a.id<b.id; } bool cmp4(point_y a,point_y b) { return a.id<b.id; } int main(){ while(~scanf("%d",&n)&&n){ bool ok = true; for(int i=0;i<n;i++) { scanf("%d%d%d%d",&a[i].x1,&b[i].y1,&a[i].x2,&b[i].y2); a[i].id = b[i].id = i+1; } sort(a,a+n,cmp); memset(vis,0,sizeof(vis)); int cnt = 0; for(int i=0;i<n;i++) { bool flage = true; for(int j=a[i].x1;j<=a[i].x2;j++){ if(!vis[j]) { vis[j] = 1; a[i].v = j; break; } if(j==a[i].x2) flage = false; } if(!flage) { ok = false; break; } } sort(b,b+n,cmp2); memset(vis,0,sizeof(vis)); cnt = 0; for(int i=0;i<n;i++) { bool flage = true; for(int j=b[i].y1;j<=b[i].y2;j++){ if(!vis[j]) { vis[j] = 1; b[i].v = j; break; } if(j==b[i].y2) flage = false; } if(!flage) { ok = false; break; } } if(ok) { sort(a,a+n,cmp3); sort(b,b+n,cmp4); for(int i=0;i<n;i++){ printf("%d %d\n",a[i].v,b[i].v); } } else printf("IMPOSSIBLE\n"); } return 0; }
原文地址:http://blog.csdn.net/weizhuwyzc000/article/details/45724585