UVA 11134 Fabled Rooks
Posted sahdsg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA 11134 Fabled Rooks相关的知识,希望对你有一定的参考价值。
https://vjudge.net/problem/UVA-11134
题目
你的任务是在 $n imes n$ 的棋盘上放 $n$ 个车,使得任意两个车不互相攻击,且第 $i$ 个车在一个给定的矩形 $R_i$ 之内。用4个整数 $xl_i, yl_i, xr_i, yr_i (1leqslant xl_ileqslant xr_i leqslant n, 1leqslant yl_i leqslant yr_i leqslant n)$ 描述第i个矩形,其中 $(xl_i, yl_i)$ 是左上角的坐标, $(xr_i, yr_i)$ 是右下角坐标,则第 $i$ 个车的位置 $(x,y)$ 必须满足 $xl_ileqslant x leqslant xr_i, yl_ileqslant y leqslant yr_i$。如果无解,输出IMPOSSIBLE;否则输出 $n$ 行,依次为第 $1,2,cdots,n$ 个车的坐标。
题解
终于不做搜索了!
贪心……
将两个维度分开
法1:
将每个区间按左端点从小到大排序
1.l1<l2时,l1到min(r1,l2)的范围内随便选,不会丢解,因此下面不再考虑左端点不等的情况
2.l1=l2时,需要考虑r1和r2的关系
显然先选r2小的……
如果按照这个策略还会出错,因为每次选择后每个区间能选的部分都会缩小一截,因为我们之前考虑的全是能选的区间……
解决方法是选择一个点后,把所有左端点相等的区间的左端点向后移动一个单位,然后再次排序……
由于重新排序有点麻烦,因此可以使用优先队列(堆)
法2:
将每个区间按右端点大小排序
显然先选右端点小的……
然后从左至右依次尝试……需要一个数组记录每个点是否选择
可以验证从左至右不会丢解
(感觉像是知道了答案编过程……还是记下,防止以后忘记)
AC代码:
#include<bits/stdc++.h> using namespace std; #define REP(r,x,y) for(register int r=(x); r<(y); r++) #define REPE(r,x,y) for(register int r=(x); r<=(y); r++) #ifdef sahdsg #define DBG(...) printf(__VA_ARGS__) #else #define DBG(...) #endif struct node { int xl,yl,xr,yr; int id; } nodes[5007]; inline bool cmp1(const node& n1, const node &n2) { return n1.xr<n2.xr || (n1.xr==n2.xr && n1.xl<n2.xl); } inline bool cmp2(const node& n1, const node &n2) { return n1.yr<n2.yr || (n1.yr==n2.yr && n1.yl<n2.yl); } bool visx[5007]; bool visy[5007]; int main() { #ifdef sahdsg freopen("in.txt", "r", stdin); #endif int n; while(~scanf("%d", &n) && n) { int ans[5007][2]; memset(visx,0,sizeof visx); memset(visy,0,sizeof visy); REP(i,0,n) { nodes[i].id=i; scanf("%d%d%d%d", &nodes[i].xl, &nodes[i].yl, &nodes[i].xr, &nodes[i].yr); } sort(nodes,nodes+n,cmp1); REP(i,0,n) { bool f=true; REPE(j,nodes[i].xl,nodes[i].xr) { if(!visx[j]) { visx[j]=1; f=false; ans[nodes[i].id][0]=j; break; } } if(f) { goto wa; } } sort(nodes,nodes+n,cmp2); REP(i,0,n) { bool f=true; REPE(j,nodes[i].yl,nodes[i].yr) { if(!visy[j]) { visy[j]=1; f=false; ans[nodes[i].id][1]=j; break; } } if(f) { goto wa; } } REP(i,0,n) { printf("%d %d ", ans[i][0], ans[i][1]); } continue; wa:; puts("IMPOSSIBLE"); } return 0; }
以上是关于UVA 11134 Fabled Rooks的主要内容,如果未能解决你的问题,请参考以下文章