UVa 11134 Fabled Rooks
题目大意:
给你n*n的棋盘,上面放n个车,使得任意两车互不攻击,要求第i个车在矩形Ri内.
若存在输出一组解,否则输出”IMPOSSIBLE”.
题目分析:
因为是在n*n的棋盘上放n个车,其实就有点类似于n皇后问题的放置方法,显然每行每列都要放一个,并且行与列是独立的,互不影响.
那么,若单独考虑行,矩形就被压缩成了线段,将线段看成是区间.实际上问题就转化为一段长为n的区间内,放置n个点,使得任意区间上都有点.
对于行和列各做一次这个操作即可.
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=5000+10;
struct Line {
int id,l,r;
Line(){}
Line(int id,int l,int r):id(id),l(l),r(r){}
bool operator < (const Line& rhs) const {
return l>rhs.l||(l==rhs.l&&r>rhs.r);
}
}x[maxn],y[maxn];
int ans[2][maxn],n;
bool solve(Line* L,int* Ans)//L指当前区间集合
{
priority_queue<Line>q;
for(int i=0;i<n;i++) q.push(L[i]);
int now=1;//now表示当前要取的坐标
while(!q.empty()) {
Line u=q.top(); q.pop();
if(u.l>now||u.r<now) return false;//若区间左端点在now以右或右端点在now以左
if(u.l<now) u.l=now,q.push(u);//因为q当中元素的l一直在更新,所以可能会出现l>r的情况
else Ans[u.id]=now++;
}
return true;
}
int main()
{
while(scanf("%d",&n)==1&&n) {
for(int i=0;i<n;i++) {
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
x[i]=Line(i,a,c);
y[i]=Line(i,b,d);
}
if(solve(x,ans[0])&&solve(y,ans[1]))//因为x与y是相互独立的,所以可以分别判断
for(int i=0;i<n;i++) printf("%d %d\n",ans[0][i],ans[1][i]);
else printf("IMPOSSIBLE\n");
}
return 0;
}