题意:在一个n*n的棋盘上放n个车,不互相攻击,每个车有自己放置的范围(一个矩形) 求放置方案
两个车不互相攻击的条件是既不在同一行也不在同一列 。而关键在于:行和列其实是无关的,可以分开单独处理。
现在问题变成一维的了,每个车有一个左右的区间,求放置方案。因为n个格子,n个车,每个格子都要放车,每个车也都要被放置。
那么对当前第i个格子,首先要知道有哪些车的可放置区间包含它,而这些车就是可选择的。
处理哪些车可选时,可以用结构体排序,按照区间左端点来排,这要枚举到格子i 时 把所以 l==i 的区间入列即可
(而如果之前放进了的某个区间的r 小于i 还没被删除 那么这个车就没被放置 即无解了)
那么选哪个最优呢?
我们应该选择可选择的车中区间右端点最小的那个,因为右端点最小的那个最容易在i 向下一个移动时,就无法放置了。
所以我们可以再用一个优先队列来维护区间的右端点和编号 这样每次取出右端点最小的 如果已经小于当前i 就是无解
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
#define scnaf scanf
#define cahr char
#define bug puts("bugbugbug");
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1000000007;
const int maxn=5000+10;
const int inf=1e9;
struct T
{
int l,r,id;
bool operator < (const T &b) const
{
if(l!=b.l)
return l<b.l;
return r<b.r;
}
} x[maxn],y[maxn];
struct T2
{
int x,y;
} ans[maxn];
priority_queue<pii,vector<pii>,greater<pii> > q;
int n;
bool go()
{
int cnt=0;
while(!q.empty())q.pop();
for(int i=1; i<=n; i++)
{
while(cnt<n&&x[cnt].l<=i)
q.push((pii){x[cnt].r,x[cnt].id}),cnt++;
if(q.empty())return 0;
pii now=q.top();
q.pop();
if(now.first<i) return 0;
ans[now.second].x=i;
}
cnt=0;
while(!q.empty())q.pop();
for(int i=1; i<=n; i++)
{
while(cnt<n&&y[cnt].l<=i)
q.push((pii){y[cnt].r,y[cnt].id}),cnt++;
if(q.empty())return 0;
pii now=q.top();
q.pop();
if(now.first<i) return 0;
ans[now.second].y=i;
}
return 1;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
for(int i=0; i<n; i++)
{
x[i].id=y[i].id=i;
scanf("%d%d%d%d",&x[i].l,&y[i].l,&x[i].r,&y[i].r);
}
sort(x,x+n);
sort(y,y+n);
if(go()){
for(int i=0;i<n;i++)
printf("%d %d\n",ans[i].x,ans[i].y);
}
else puts("IMPOSSIBLE");
}
}