这道题目可以把问题分解, 因为x坐标和y坐标的答案之间没有联系, 所以可以
单独求两个坐标的答案
我一开始想的是按照 左区间从小到大, 相同的时候从右区间从小到大排序, 然后WA
去uDebug找了数据, 发现这组数据过不了
3
1 1 3 3
1 1 3 3
2 2 2 2
正确输出是
1 1
3 3
1 1
2 2
我输出 IMPOSSIBLE
我发现当 有包含关系的时候, 会先处理大区间而把小区间应该放的点覆盖掉了。所以我这个方法是不行滴, 然后就暂时不知道怎么改了。
我一开始想的是按照 左区间从小到大, 相同的时候从右区间从小到大排序, 然后WA
去uDebug找了数据, 发现这组数据过不了
3
1 1 3 3
1 1 3 3
2 2 2 2
正确输出是
1 1
3 3
1 1
2 2
我输出 IMPOSSIBLE
我发现当 有包含关系的时候, 会先处理大区间而把小区间应该放的点覆盖掉了。所以我这个方法是不行滴, 然后就暂时不知道怎么改了。
之后我去看了他人的博客发现是按 右区间从小到大排序, 左区间从大到小排序,然后从左端点开始放, 放过就跳过, 如果放不了就无解。这种排序方式, 有包含关系的时候, 小的会先处理, 不会出现大的先处理然后覆盖了小区间的情况。
所以这类
区间的问题,
排序方式应该是这种排序方式比较通用, 紫书前面讲贪心法的时候都是这么排序的。
除此之外要考虑
区间包含问题, 这道题的包含问题排序的时候就直接解决了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;const int MAXN = 5123;
struct node
{int l, r, id;
}x[MAXN], y[MAXN];
int ansx[MAXN], ansy[MAXN], vis[MAXN], n, ok;bool cmp(node x, node y)
{if(x.r != y.r)return x.r < y.r;return x.l > y.l;
}bool work(node *t, int p) //两次求坐标可以写在一起
{memset(vis, 0, sizeof(vis));sort(t, t + n, cmp);REP(i, 0, n){int pos = t[i].l;while(1){if(!vis[pos]) {vis[pos] = 1;if(p == 0) ansx[t[i].id] = pos;else ansy[t[i].id] = pos;break;}else pos++;if(pos > t[i].r) return false;}}return true;
}int main()
{while(~scanf("%d", &n) && n){REP(i, 0, n){scanf("%d%d%d%d", &x[i].l, &y[i].l, &x[i].r, &y[i].r);x[i].id = y[i].id = i;}if(work(x, 0) && work(y, 1)){REP(i, 0, n)printf("%d %d\n", ansx[i], ansy[i]);}else puts("IMPOSSIBLE");}return 0;
}