解题报告 之 UVA11134 Fabled Rooks

解题报告 之 UVA11134 Fabled Rooks

Description

Download as PDF

Problem F: Fabled Rooks

We would like to place  n rooks, 1 ≤   n ≤ 5000, on a  n×nboard subject to the following restrictions
  • The i-th rook can only be placed within the rectangle given by its left-upper corner (xliyli) and its right-lower corner (xriyri), where 1 ≤ i ≤ n, 1 ≤ xli ≤ xri ≤ n, 1 ≤ yli ≤ yri ≤ n.
  • No two rooks can attack each other, that is no two rooks can occupy the same column or the same row.

The input consists of several test cases. The first line of each of them contains one integer number, n, the side of the board.n lines follow giving the rectangles where the rooks can be placed as described above. The i-th line among them gives xli,ylixri, and yri. The input file is terminated with the integer `0' on a line by itself.

Your task is to find such a placing of rooks that the above conditions are satisfied and then outputn lines each giving the position of a rook in order in which their rectangles appeared in the input. If there are multiple solutions, any one will do. Output IMPOSSIBLE if there is no such placing of the rooks.

Sample input

8
1 1 2 2
5 7 8 8
2 2 5 5
2 2 5 5
6 3 8 6
6 3 8 5
6 3 8 8
3 6 7 8
8
1 1 2 2
5 7 8 8
2 2 5 5
2 2 5 5
6 3 8 6
6 3 8 5
6 3 8 8
3 6 7 8
0

Output for sample input

1 1
5 8
2 4
4 2
7 3
8 5
6 6
3 7
1 1
5 8
2 4
4 2
7 3
8 5
6 6
3 7


题目大意:n*n的棋盘上有n个车,使得任意两个车不在同一列且任意两个车不在同一行。且每个车的位置在给出的两个坐标为对角线的矩形内。试构造出一种摆法。

这一题的主要注意到的是行和列没关系,按照书上的说法就是问题分解,分别考虑行和列的情况,而且是对称的。所以将二维问题分解为两个一维问题,用贪心法解题。

先考虑行,我们按照范围起点大小排序,然后尽可能输出比较靠前的位置(给后面的点留下空间)。但第二个坑点就是两个车的行范围可能有重复,如果在范围起点一致的情况下,要先处理范围小的(即范围终点),否则有可能就会误操作。所以我排序的方法是采用先按照范围起点(xl)排序,再按照范围终点(xr)排序。但是会出一个问题就是前面的某个点被占用了之后其他的点并没有更新其起点,所以我又加了一个关于m的限制,然后每一个车选择完位置之后再将未确定位置的车排序一次(其目的是更新起点)。

然后上代码:
#include <iostream>
#include <algorithm>
#define MAXN 5010
using namespace std;

struct car
{
	int xl, yl, xr, yr;
	int x, y;
	int order;
};

car cars[MAXN];
int m;

bool cmp1(const car& lhs, const car& rhs)
{
	int tem1 = lhs.xl > m ? lhs.xl : m + 1;
	int tem2 = rhs.xl > m ? rhs.xl : m + 1;
	if (tem1 == tem2)	return lhs.xr < rhs.xr;
	return tem1 < tem2;
}

bool cmp2(const car& lhs, const car& rhs)
{
	int tem1 = lhs.yl > m ? lhs.yl : m + 1;
	int tem2 = rhs.yl > m ? rhs.yl : m + 1;
	if (tem1 == tem2)	return lhs.yr < rhs.yr;
	return tem1 < tem2;
}

bool cmp3(const car& lhs, const car& rhs)
{
	return lhs.order < rhs.order;
}

int main()
{
	int n;
	while (cin >> n&&n)
	{
		for (int i = 0; i < n; i++)

		{
			cin >> cars[i].xl >> cars[i].yl >> cars[i].xr >> cars[i].yr;
			cars[i].order = i;
		}
		m = 0;
		int flag = true;
		for (int i = 0; i < n; i++)
		{
			sort(cars + i, cars + n, cmp1);
			if (m < cars[i].xr)
			{
				cars[i].x = m = max(m + 1, cars[i].xl);
			}
			else
			{
				flag = false;
				break;
			}
		}
		if (!flag)
		{
			cout << "IMPOSSIBLE" << endl;
			continue;
		}

		flag = true, m = 0;
		for (int i = 0; i < n; i++)
		{
			sort(cars + i, cars + n, cmp2);
			if (m < cars[i].yr)
			{
				cars[i].y = m = max(m + 1, cars[i].yl);
			}
			else
			{
				flag = false;
				break;
			}
		}
		if (!flag)
		{
			cout << "IMPOSSIBLE" << endl;
			continue;
		}

		sort(cars, cars + n, cmp3);
		for (int i = 0; i < n; i++)
			cout << cars[i].x << " " << cars[i].y << endl;
	}
}

哎呀一周19道看来的确是吃不消啊,,队长你看着办。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值