x轴,y轴不相关,所以分开考虑
贪心法 可以这样思考,不同于定区间选点,而是定点选区间,那么怎么对区间排序最优?
假设前提是从1开始取点放,对于其中x这个点,假设有很多区间[a,b]包含x这个点,那么对于那么多的区间我们只要选取b最小的就好,注意是在包含x的区间中选!!
但为了加快选中的概率,再加一条规则:b相同时取a最小的区间,毕竟区间越长包含x的概率大;
再理一遍:
1) b最小 : 因为1~x-1都是放好了的已经,而x+1~n还未放位置,所以我们要给后来的多多留位置;
2)b相同时取a最小的区间 :对于b相同,相比更长的区间覆盖到x的几率更大,所以我们要排在前面;
综上[a,b]区间要按b优先排序,b相同时a取小;
另外,因为是从1开始放点,如果出现一个区间a<x&& b<x,肯定是问题无解的,因为前1~x-1的点还没选走这个区间,那么以后肯定没有任何一个点能放在这个区间。
比如说 [1,1],[2,2],[1,3] 按a大小排序[1,1],[1,3],[2,2] 是错误的而按b大小排序[1,1],[2,2], [1,3]才是对的
代码如下:
#include<iostream>
#include<vector>
#include<queue>
#include<numeric>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<ctime>
using namespace std;
const int maxn=5000+5;
int n,x1[maxn],x2[maxn],y1[maxn],y2[maxn],x[maxn],y[maxn];bool solve(int* a,int *b,int* c) //[a,b]
{memset(c,-1,sizeof(int)*n); // a[i] <= col <= b[i]/*fill(c,c+n,-1) 是对每一个int大小内存块初始化,而memset是对每个字节*/ for(int col=1;col<=n0;col++) //在1~n给每个区间放个root {int root=-1,minb=n+1;for(int i=0;i<n;i++)if(c[i]<0&&a[i]<=col&& b[i]<minb) root=i,minb=b[i];//对于每个未放的区间选b最小的if(root<0||minb<col) return false;//if(放不了了||col为要放的位置>b即col在区间[a,b]外) c[root]=col;}return true;
}int main()
{while(scanf("%d",&n)==1&&n){for(int i=0;i<n;i++)scanf("%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i]);if(solve(x1,x2,x)&&solve(y1,y2,y))for(int i=0;i<n;i++) printf("%d %d\n",x[i],y[i]);else printf("IMPOSSIBLE\n");}
}
优化一下,直接按上述规则排序后再选区间,更加省时间;
RunTime :从140ms到20ms
#include<iostream>
#include<vector>
#include<queue>
#include<numeric>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<ctime>
using namespace std;
const int maxn=5000+5;
int n,x[maxn],y[maxn];
struct point
{int a,b,p; //[a,b] 第p个点要放置的区间
}x1[maxn],y1[maxn];bool cmp(const point& a,const point& b)
{if(a.b!=b.b) return a.b<b.b;else return a.a<b.a;
}bool solve(point* x,int* c)
{sort(x,x+n,cmp);memset(c,-1,sizeof(int)*n); for(int col=1;col<=n;col++) {int root=-1,b=n+1;for(int i=0;i<n;i++)if(c[x[i].p]<0&&x[i].a<=col) {root=i,b=x[i].b;break;}if(root<0||b<col) return false;c[x[root].p]=col;}return true;
}int main()
{while(scanf("%d",&n)==1&&n){for(int i=0;i<n;i++)scanf("%d%d%d%d",&x1[i].a,&y1[i].a,&x1[i].b,&y1[i].b),x1[i].p=y1[i].p=i;if(solve(x1,x)&&solve(y1,y))for(int i=0;i<n;i++) printf("%d %d\n",x[i],y[i]);else printf("IMPOSSIBLE\n");}
}