码迷,mamicode.com
首页 > 其他好文 > 详细

UVA 11134 Fabled Rooks

时间:2019-03-05 21:45:20      阅读:225      评论:0      收藏:0      [点我收藏+]

标签:选择   记录   tin   移动   lap   size   ...   goto   范围   

https://vjudge.net/problem/UVA-11134

题目

你的任务是在 $n\times n$ 的棋盘上放 $n$ 个车,使得任意两个车不互相攻击,且第 $i$ 个车在一个给定的矩形 $R_i$ 之内。用4个整数 $xl_i, yl_i, xr_i, yr_i (1\leqslant xl_i\leqslant xr_i \leqslant n, 1\leqslant yl_i \leqslant yr_i \leqslant n)$ 描述第i个矩形,其中 $(xl_i, yl_i)$ 是左上角的坐标, $(xr_i, yr_i)$ 是右下角坐标,则第 $i$ 个车的位置 $(x,y)$ 必须满足 $xl_i\leqslant x \leqslant xr_i, yl_i\leqslant 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\n", ans[i][0], ans[i][1]);
		}
		
		continue;
		wa:;
		puts("IMPOSSIBLE");
		
	}
	
	return 0;
}

 

UVA 11134 Fabled Rooks

标签:选择   记录   tin   移动   lap   size   ...   goto   范围   

原文地址:https://www.cnblogs.com/sahdsg/p/10479634.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!