题意:

给出若干个栋楼俯视图的坐标和面积,求从俯视图的南面(可以视为正视图)看过去到底能看到多少栋楼。

输入第一个n说明有n栋楼,然后输入5个实数(注意是实数),分别是楼的左下角坐标(x,y), 然后楼的x方向的宽度,y方向的深度,还有楼的高度。

按横坐标,横坐标同样按纵坐标排序输出所有能看到的楼。

分析:

先记录一个一开始就想错的做法:

以为只要把x 和 width放大到到足够大(例如10000倍,倍数越高精度越高),然后排序填充一下数轴就可以,就可以解决x坐标是小数的问题。但这样打了一下,发现第一计算速度很慢(放大后n倍计算量也同时放大n^2倍), 第二是无法处理覆盖与重叠的部分, 只会保留数轴中最大的部分, 无法保留在高楼南边的矮楼,第三这种做法也是错误的,只要他是连续的,就算放大也不能完全保证算法正确性。

正确的做法应该是将正视图x轴离散化:

首先这题楼的可见性可以简化成建筑物南面的墙的可见性(可在上图感受一下),所以输入的深度这个属性是没有用的,可以用%*lf(在键盘上读取但不保存)在输入时忽略掉。

接下来就是离散化的核心,提取正视图x轴有用的点,先无限个x的取值化为有限的关键点。

——按每栋楼的x的最左边和最右边看成区间的两个端点, 然后将整张图分为多个区间, 然后可以保证每个区间整片区间一定包含其中一栋楼, 只要判断这个区间包含的楼是否可见即可。

分割如下:

可以观察, 每个区间的任何一个点都拥有同样的性质,即无论从区间的哪一个点观察,都可得到同样的结果。

不妨取每个区间的中点作为关键点

可以先按输出要求遍历所有的楼,每栋楼再遍历所有的区间,然后再判断能否被看见。

如何判断是否能看见?

看见只要满足两个条件:

设这栋楼为A。

①A在其中一个区间内(或者说忽略高度条件,在这个区间的中点能看见A), 即 楼的最左端 <=该区间中点 && 楼的最右端>=该区间中点 

②该区间内比A的y坐标小的楼都比A矮。(如果在A的南面有比他高的,那么自然看不见A)

  这个点又可以判断为两个条件

  1.是否有楼在这个区间内(判断方法同①,所以这种需要重复判断的条件最好写成一个函数

  2.该楼是否比A矮(判断一下高度即可)

此外这题还涉及一个STL函数,unique,它通常使用在sort后的数组, 将不同的元素保留在数组前面, 然后那些重复元素移到后面。原型可以为unique(v.begin(),v.end()); 

如果想更深入了解离散化思想可以看看matrix67的博客——http://www.matrix67.com/blog/archives/108

 #include<bits/stdc++.h>
using namespace std;
struct Bd
{
double x,y, width, high;
int num;
bool operator < (const Bd& rhs)const{
return x<rhs.x ||(x==rhs.x && y < rhs.y);
}
}b[];
int n;
bool can_see(int i, int mx)//判断第i栋楼在不在中点上
{
return b[i].x <= mx && (b[i].x + b[i].width >= mx);
}
bool visible(int i, int mx)//包含高度条件,在中点能不能看到第i栋楼
{
if(!can_see(i, mx)) return false;
for(int k = ; k < n;k++)
{
if(b[k].y < b[i].y && b[k].high >= b[i].high && can_see(k,mx)) return false;
}
return true;
}
int main()
{
#if LOCAL
freopen("1.txt","r",stdin);
#endif // LOCAL
int kase = ;
while(scanf("%d", &n) && n)
{
double w[];
for(int i = ; i < n ; i++)
{
double tx, ty, tw, th;
scanf("%lf %lf %lf %*lf %lf", &tx, &ty, &tw, &th);
b[i].x = tx;
b[i].y = ty;
b[i].width = tw;
b[i].high = th;
b[i].num = i+;
w[i*] = tx;
w[i*+] = tx + tw;
}
sort(b,b+n);
sort(w,w+*n);
int m = unique(w,w+*n) - w;
if(kase != ) printf("\n");
printf("For map #%d, the visible buildings are numbered as follows:\n%d",kase++, b[].num);//第一栋楼在左下角,肯定能看到
for(int i = ; i < n; i++)
{
int is = ;
for(int j = ; j < m - ; j++)
{
if(visible(i,(w[j]+w[j+])/))
{
is = ;
break;
}
}
if(is) printf(" %d", b[i].num);
}
printf("\n");
}
}

UVA 221 城市化地图(离散化思想)的更多相关文章

  1. UVa 221 Urban Elevations 城市正视图 离散化初步 无限化有限

    转载请注明: 仰望高端玩家的小清新 http://www.cnblogs.com/luruiyuan/ 题目大意: 题目传送门:UVa 221 Urban Elevations 给出城市中建筑物的x, ...

  2. HDU5124:lines(线段树+离散化)或(离散化思想)

    http://acm.hdu.edu.cn/showproblem.php?pid=5124 Problem Description John has several lines. The lines ...

  3. UVa 221城市正视图(离散化)

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  4. UVA 221 - Urban Elevations(离散化)!!!!!!

    题意:给出一张俯视图.给出N个建筑物的左下标,长度,宽度,高度.现在求,从南面看,能看到那些建筑? Sample Input 14 160 0 30 60 30 125 0 32 28 60 95 0 ...

  5. UVa 221 (STL 离散化) Urban Elevations

    题意: 作图为n个建筑物的俯视图,右图为从南向北看的正视图,按从左往右的顺序输出可见建筑物的标号. 分析: 题中已经说了,要么x相同,要么x相差足够大,不会出现精度问题. 给这n个建筑物从左往右排序, ...

  6. 【紫书】Urban Elevations UVA - 221 离散化

    题意:给你俯视图,要求依次输出正视图中可以看到的建筑物 题解:任意相邻的x间属性相同,所以离散化. 坑:unique只能对数组用.下标易错 list不能找某元素的next.用了个很麻烦的处理 数组: ...

  7. 此坑待填 离散化思想和凸包 UVA - 10173 Smallest Bounding Rectangle

    Smallest Bounding Rectangle Given the Cartesian coordinates of n(>0)2-dimensional points, write a ...

  8. hdu 2771(uva 12171) Sculpture bfs+离散化

    题意: 给出一些边平行于坐标轴的长方体,这些长方体可能相交.也可能相互嵌套.这些长方体形成了一个雕塑,求这个雕塑的整体积和表面积. 题解: 最easy想到直接进行bfs或者dfs统计,但此题的麻烦之处 ...

  9. UVA 10891 区间DP+博弈思想

    很明显带有博弈的味道.让A-B最大,由于双方都采用最佳策略,在博弈中有一个要求时,让一方的值尽量大.而且由于是序列,所以很容易想到状态dp[i][j],表示序列从i到j.结合博弈中的思想,表示初始状态 ...

随机推荐

  1. 我的spring cloud项目历程(2018.3~2018.9)

    前言 今天是9月17日,趁着山竹的临幸,得以在家里舒适的办公.项目从3月底开始,至今刚好半年.抽几十分钟,总结下半年的历程.对后面的项目,应该也有一点帮助吧. 学习前的七个问题 项目开始前,由于某些特 ...

  2. 进击的Python【第七章】:python各种类,反射,异常处理和socket基础

    Python的高级应用(三)面向对象编程进阶 本章学习要点: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 一.面向对象高级语法部分 静态方法 ...

  3. 51nod 1138 连续整数的和

    1138 连续整数的和  基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题  收藏  关注 给出一个正整数N,将N写为若干个连续数字和的形式(长度 >= 2). ...

  4. 洛谷 P2742 [USACO5.1]圈奶牛Fencing the Cows || 凸包模板

    整篇都是仅做记录... 蓝书上的板子.水平序,单调栈.先求下凸包,再求上凸包.叉积的作用是判定向量的位置关系. 48行的作用是在求上凸包的时候不至于去删下凸包中的点.上凸包中第一个点被认为是t1. 另 ...

  5. Android开发学习--RecycleView入门

    该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView.GridView 通过设置它提供的不同LayoutManager,ItemDecoration , It ...

  6. ES之事件绑定,解除绑定以及事件冒泡、事件捕获

    绑定事件的处理方法任何元素都有事件属性,而绑定事件就是将这个事件与一个函数相连接. ①句柄事件dom.onXXX = function () {代码块} 以on开头的事件属于句柄事件兼容性非常好,但是 ...

  7. iOS Programming Localization 本地化

    iOS Programming Localization 本地化 Internationalization is making sure your native cultural informatio ...

  8. VB6程序中NULL注意事项

    VB6中从数据库中取出栏位值进行操作,若栏位值为Null,则必须小心处理,否则极易导致程序出错退出. 通常我们从recordset中取出栏位值采用Fields方法,加上栏位名称,如 rsMoney.F ...

  9. 关于 Oracle 11g r2 Enterprise Manager (EM) 在windows环境无法启动的解决办法

    正确的解决办法是在安装的时候使用emca正确安装 如果已经安装过Enterprise Manager: 请用是如下命令卸载后重装 emca -deconfig dbcontrol db emca -r ...

  10. Node.js——开放静态资源原生写法

    借助了mime第三方包,根据请求地址请求的文件后缀,设置content-type