UVA - 11134 - Fabled Rooks(贪心)
题意:给定n(n <= 5000)个车,给出每个车的可放置范围(一个矩形区域),给出任意一种放置方法使得任意两个车不能相互攻击,若没有方法则输出“IMPOSSIBLE”。
分成横纵两个方向进行研究(每个方向上只要不在同一条线上即可)。
贪心,先将每个车的范围按照先 a.r < b.r 后 a.l < b.l 的顺序排序,然后尽量将每个车往左排即可。
(将越能到达右边的位置的车,尽可能往后排,若可以放的最右边的位置相同(a.r == b.r),则更能往左延伸的车在前,因为排序时是尽量靠左排)
#include<cstdio> #include<cstring> #include<cctype> #include<cstdlib> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<deque> #include<queue> #include<stack> #include<list> typedef long long ll; typedef unsigned long long llu; const int MAXN = 5000 + 10; const int MAXT = 200000 + 10; const int INF = 0x7f7f7f7f; const double pi = acos(-1.0); const double EPS = 1e-6; using namespace std; int n, ans[MAXN][2], vis[MAXN]; struct Node{ int l, r, id; bool operator < (const Node &b) const{ return r < b.r || (r == b.r && l < b.l); } }one[MAXN], two[MAXN]; bool solve(Node *a, int cur){ sort(a, a + n); memset(vis, 0, sizeof vis); int lur = 0; for(int i = 0; i < n; ++i){ bool flag = false; for(int j = a[i].l; j <= a[i].r; ++j) if(!vis[j]){ vis[j] = 1; ans[a[i].id][cur] = j; flag = true; break; } if(!flag) return false; } return true; } int main(){ while(scanf("%d", &n) == 1 && n){ memset(ans, 0, sizeof ans); for(int i = 0; i < n; ++i){ scanf("%d%d%d%d", &one[i].l, &two[i].l, &one[i].r, &two[i].r); one[i].id = two[i].id = i + 1; } if(!solve(one, 0)){ printf("IMPOSSIBLE\n"); continue; } if(!solve(two, 1)) printf("IMPOSSIBLE\n"); else for(int i = 1; i <= n; ++i) printf("%d %d\n", ans[i][0], ans[i][1]); } return 0; }