UVA 221 城市化地图(离散化思想)
题意:
给出若干个栋楼俯视图的坐标和面积,求从俯视图的南面(可以视为正视图)看过去到底能看到多少栋楼。
输入第一个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 城市化地图(离散化思想)的更多相关文章
- UVa 221 Urban Elevations 城市正视图 离散化初步 无限化有限
转载请注明: 仰望高端玩家的小清新 http://www.cnblogs.com/luruiyuan/ 题目大意: 题目传送门:UVa 221 Urban Elevations 给出城市中建筑物的x, ...
- HDU5124:lines(线段树+离散化)或(离散化思想)
http://acm.hdu.edu.cn/showproblem.php?pid=5124 Problem Description John has several lines. The lines ...
- UVa 221城市正视图(离散化)
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- UVA 221 - Urban Elevations(离散化)!!!!!!
题意:给出一张俯视图.给出N个建筑物的左下标,长度,宽度,高度.现在求,从南面看,能看到那些建筑? Sample Input 14 160 0 30 60 30 125 0 32 28 60 95 0 ...
- UVa 221 (STL 离散化) Urban Elevations
题意: 作图为n个建筑物的俯视图,右图为从南向北看的正视图,按从左往右的顺序输出可见建筑物的标号. 分析: 题中已经说了,要么x相同,要么x相差足够大,不会出现精度问题. 给这n个建筑物从左往右排序, ...
- 【紫书】Urban Elevations UVA - 221 离散化
题意:给你俯视图,要求依次输出正视图中可以看到的建筑物 题解:任意相邻的x间属性相同,所以离散化. 坑:unique只能对数组用.下标易错 list不能找某元素的next.用了个很麻烦的处理 数组: ...
- 此坑待填 离散化思想和凸包 UVA - 10173 Smallest Bounding Rectangle
Smallest Bounding Rectangle Given the Cartesian coordinates of n(>0)2-dimensional points, write a ...
- hdu 2771(uva 12171) Sculpture bfs+离散化
题意: 给出一些边平行于坐标轴的长方体,这些长方体可能相交.也可能相互嵌套.这些长方体形成了一个雕塑,求这个雕塑的整体积和表面积. 题解: 最easy想到直接进行bfs或者dfs统计,但此题的麻烦之处 ...
- UVA 10891 区间DP+博弈思想
很明显带有博弈的味道.让A-B最大,由于双方都采用最佳策略,在博弈中有一个要求时,让一方的值尽量大.而且由于是序列,所以很容易想到状态dp[i][j],表示序列从i到j.结合博弈中的思想,表示初始状态 ...
随机推荐
- 我的spring cloud项目历程(2018.3~2018.9)
前言 今天是9月17日,趁着山竹的临幸,得以在家里舒适的办公.项目从3月底开始,至今刚好半年.抽几十分钟,总结下半年的历程.对后面的项目,应该也有一点帮助吧. 学习前的七个问题 项目开始前,由于某些特 ...
- 进击的Python【第七章】:python各种类,反射,异常处理和socket基础
Python的高级应用(三)面向对象编程进阶 本章学习要点: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 一.面向对象高级语法部分 静态方法 ...
- 51nod 1138 连续整数的和
1138 连续整数的和 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 关注 给出一个正整数N,将N写为若干个连续数字和的形式(长度 >= 2). ...
- 洛谷 P2742 [USACO5.1]圈奶牛Fencing the Cows || 凸包模板
整篇都是仅做记录... 蓝书上的板子.水平序,单调栈.先求下凸包,再求上凸包.叉积的作用是判定向量的位置关系. 48行的作用是在求上凸包的时候不至于去删下凸包中的点.上凸包中第一个点被认为是t1. 另 ...
- Android开发学习--RecycleView入门
该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView.GridView 通过设置它提供的不同LayoutManager,ItemDecoration , It ...
- ES之事件绑定,解除绑定以及事件冒泡、事件捕获
绑定事件的处理方法任何元素都有事件属性,而绑定事件就是将这个事件与一个函数相连接. ①句柄事件dom.onXXX = function () {代码块} 以on开头的事件属于句柄事件兼容性非常好,但是 ...
- iOS Programming Localization 本地化
iOS Programming Localization 本地化 Internationalization is making sure your native cultural informatio ...
- VB6程序中NULL注意事项
VB6中从数据库中取出栏位值进行操作,若栏位值为Null,则必须小心处理,否则极易导致程序出错退出. 通常我们从recordset中取出栏位值采用Fields方法,加上栏位名称,如 rsMoney.F ...
- 关于 Oracle 11g r2 Enterprise Manager (EM) 在windows环境无法启动的解决办法
正确的解决办法是在安装的时候使用emca正确安装 如果已经安装过Enterprise Manager: 请用是如下命令卸载后重装 emca -deconfig dbcontrol db emca -r ...
- Node.js——开放静态资源原生写法
借助了mime第三方包,根据请求地址请求的文件后缀,设置content-type