zoukankan      html  css  js  c++  java
  • 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;
    }


  • 相关阅读:
    1. centos7 的安装
    编写java 程序与Linux进行远程连接并运行linux下的脚本
    java 利用辗除法求两个整数的最大公约数和最小公倍数
    java 给不同成绩分等级
    java 分解质因数
    java中导入 导出
    Mysql 常用命令
    mysql 创建联合主键
    mysql注释
    mysql管理工具navicat的快捷键
  • 原文地址:https://www.cnblogs.com/mofushaohua/p/7789443.html
Copyright © 2011-2022 走看看