UVA

/*
  这题的基本思想是坐标离散化,之前看《挑战程序设计竞赛》时,做过类似的题如下:
  
  GCJ 2008 APAC local onsites C Millionaire
  链接:http://blog.csdn.net/mofushaohua_ln/article/details/77647763
  说明:这题是概率题,虽然不算是坐标离散化,不过思路也是离散化,当时做这题时,因为是第一次接触离散化这个思想,所以理解的过程相当艰难...但是即使到了现在,我仍然觉得这是一道十分值得重做的概率题
  
  坐标离散化技巧(来自挑战)
  blog: http://blog.csdn.net/mofushaohua_ln/article/details/77795409
  
  说明:这是做的第二道离散化的题,有了前一道的基础和广搜的基础,所以这题理解时并不是很困难,不过用来复习离散化的思路还是不错的~
  
  
  ****本题思路****(详见入门经典P132)
  建筑物的可见性等价于南墙的可见性,可在输入后直接忽略“深度”参数
  
  一个建筑物可能只有部分可见,但我们不可能枚举所有的x,来查看这个建筑在该处是否可见,因为x多穷多
  
  解决方法:离散化,把无穷变为有限
  
  具体方法:所有x坐标(准确说,是每个宽度范围,对应的两个上下限的x坐标),排序去重,任意两相邻的区间具有相同属性。一个区间要么完全可见,要么完全不可见。只需在这个区间里任选一点,就能判断处一个建筑物是否在整个区间内可见。
  
  如何判断一个建筑物是否在某个坐标处可见?
  首先,建筑物坐标中必须包含这个x坐标,其次,建筑物南边不能有另外一个不比它矮的建筑物也包含这个x坐标
*/



#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 105;
int n;
double x[maxn * 2]; //记录每个建筑物的宽度范围的上下限

struct Building
{
	int id;
	double x, y, w, d, h;
	bool operator < (const Building &a) const
	{
		return x < a.x || (x == a.x && y < a.y);
	}
}b[maxn];

istream& operator >> (istream &in, Building &a)
{
	in >> a.x >> a.y >> a.w >> a.d >> a.h;
	return in;
}

bool cover (int i, double mx)
{
	return b[i].x <= mx && b[i].x + b[i].w >= mx;
}

//判断建筑物 i 在 x = mx处是否可见
bool visible (int i, double mx)
{
	if (!cover(i, mx)) return false;
	for (int k = 0; k < n; k++)
	if (b[k].y < b[i].y && b[k].h >= b[i].h && cover(k, mx)) return false;
	return true;
}

int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	
	int kase = 0;
	while (cin >> n && n)
	{
		for (int i = 0; i < n; i++)
		{
			cin >> b[i];
			x[i * 2] = b[i].x; x[i * 2 + 1] = b[i].x + b[i].w;
			b[i].id = i + 1;
		}
		
		sort(b, b + n);
		sort(x, x + 2 * n);
		
		int m = unique(x, x + n * 2) - x; //去重后,得到m个坐标
		
		if (kase++) cout << endl;
		
		cout << "For map #" << kase << ", the visible buildings are numbered as follows:" << endl << b[0].id;
		for (int i = 1; i < n; i++)
		{
			bool vis = false;
			for (int j = 0; j < m - 1; j++)
			{
				if (visible(i, (x[j] + x[j + 1]) / 2) )
				{
					vis = true;
					break;
				} 
			}
			if (vis) cout << " " << b[i].id;
		}
		cout << endl;
	}
	return 0;
}


原文地址:https://www.cnblogs.com/mofushaohua/p/7789443.html