C++ 什么叫做离散化
C++ 什么叫做离散化
如果说今年这时候OIBH问得最多的问题是二分图,那么去年这时候问得最多的算是离散化了。对于“什么是离散化”,搜索帖子你会发现有各种说法,比如“排序后处理”、“对坐标的近似处理”等等。哪个是对的呢?哪个都对。关键在于,这需要一些例子和不少的讲解才能完全解释清楚。
离散化是程序设计中一个非常常用的技巧,它可以有效的降低时间复杂度。其基本思想就是在众多可能的情况中“只考虑我需要用的值”。下面我将用三个例子说明,如何运用离散化改进一个低效的,甚至根本不可能实现的算法。
《算法艺术与信息学竞赛》中的计算几何部分,黄亮举了一个经典的例子,我认为很适合用来介绍离散化思想。这个问题是UVA10173(http://acm.uva.es/p/v101/10173.html),题目意思很简单,给定平面上n个点的坐标,求能够覆盖所有这些点的最小矩形面积。这个问题难就难在,这个矩形可以倾斜放置(边不必平行于坐标轴)。
这里的倾斜放置很不好处理,因为我们不知道这个矩形最终会倾斜多少度。假设我们知道这个矩形的倾角是α,那么答案就很简单了:矩形面积最小时四条边一定都挨着某个点。也就是说,四条边的斜率已经都知道了的话,只需要让这些边从外面不断逼近这个点集直到碰到了某个点。你不必知道这个具体应该怎么实现,只需要理解这可以通过某种方法计算出来,毕竟我们的重点在下面的过程。
我们的算法很显然了:枚举矩形的倾角,对于每一个倾角,我们都能计算出最小的矩形面积,最后取一个最小值。
这个算法是否是正确的呢?我们不能说它是否正确,因为它根本不可能实现。矩形的倾角是一个实数,它有无数种可能,你永远不可能枚举每一种情况。我们说,矩形的倾角是一个“连续的”变量,它是我们无法枚举这个倾角的根本原因。我们需要一种方法,把这个“连续的”变量变成一个一个的值,变成一个“离散的”变量。这个过程也就是所谓的离散化。
我们可以证明,最小面积的矩形不但要求四条边上都有一个点,而且还要求至少一条边上有两个或两个以上的点。试想,如果每条边上都只有一个点,则我们总可以把这个矩形旋转一点使得这个矩形变“松”,从而有余地得到更小的矩形。于是我们发现,矩形的某条边的斜率必然与某两点的连线相同。如果我们计算出了所有过两点的直线的倾角,那么α的取值只有可能是这些倾角或它减去90度后的角(直线按“\”方向倾斜时)这么C(n,2)种。我们说,这个“倾角”已经被我们 “离散化”了。虽然这个算法仍然有优化的余地,但此时我们已经达到了本文开头所说的目的。
对于某些坐标虽然已经是整数(已经是离散的了)但范围极大的问题,我们也可以用离散化的思想缩小这个规模。最近搞模拟赛Vijos似乎火了一把,我就拿两道Vijos的题开刀。
VOJ1056(http://www.vijos.cn/Problem_Show.asp?id=1056) 永远是离散化的经典问题。大意是给定平面上的n个矩形(坐标为整数,矩形与矩形之间可能有重叠的部分),求其覆盖的总面积。平常的想法就是开一个与二维坐标规模相当的二维Boolean数组模拟矩形的“覆盖”(把矩形所在的位置填上True)。可惜这个想法在这里有些问题,因为这个题目中坐标范围相当大(坐标范围为-10^8到10^8之间的整数)。但我们发现,矩形的数量n<=100远远小于坐标范围。每个矩形会在横纵坐标上各“使用”两个值, 100个矩形的坐标也不过用了-10^8到10^8之间的200个值。也就是说,实际有用的值其实只有这么几个。这些值将作为新的坐标值重新划分整个平面,省去中间的若干坐标值没有影响。我们可以将坐标范围“离散化”到1到200之间的数,于是一个200*200的二维数组就足够了。实现方法正如本文开头所说的“排序后处理”。对横坐标(或纵坐标)进行一次排序并映射为1到2n的整数,同时记录新坐标的每两个相邻坐标之间在离散化前实际的距离是多少。这道题同样有优化的余地。
最后简单讲一下计算几何以外的一个运用实例(实质仍然是坐标的离散)。才考的VOJ1238(http://www.vijos.cn/Problem_Show.asp?id=1238)中,标程开了一个与时间范围一样大的数组来储存时间段的位置。这种方法在空间上来看十分危险。一旦时间取值范围再大一点,盲目的空间开销将导致Memory Limit Exceeded。我们完全可以采用离散化避免这种情况。我们对所有给出的时间坐标进行一次排序,然后同样用时间段的开始点和结束点来计算每个时刻的游戏数,只是一次性加的经验值数将乘以排序后这两个相邻时间点的实际差。这样,一个1..n的数组就足够了。
离散化的应用相当广泛,以后你会看到还有很多其它的用途。
2007.04.05补充:
VOJ1056那个例子看来还是有人不明白。
我发一张示意图,注意左边的10*7的数组是如何等价地转化为右边两个4*4的数组的
C++ 什么叫做离散化的更多相关文章
- NBUT 1457 莫队算法 离散化
Sona Time Limit:5000MS Memory Limit:65535KB 64bit IO Format: Submit Status Practice NBUT 145 ...
- 项目安排(离散化+DP)
题目来源:网易有道2013年校园招聘面试二面试题 题目描述: 小明每天都在开源社区上做项目,假设每天他都有很多项目可以选,其中每个项目都有一个开始时间和截止时间,假设做完每个项目后,拿到报酬都是不同的 ...
- P1774 最接近神的人_NOI导刊2010[树状数组 逆序对 离散化]
题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着“神的殿堂”.小FF猜想里面应该就有王室的 ...
- 洛谷P1462 通往奥格瑞玛的道路[二分答案 spfa 离散化]
题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛 题目描述 在艾泽拉斯, ...
- POJ1151Atlantis 矩形面积并[线段树 离散化 扫描线]
Atlantis Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 21734 Accepted: 8179 Descrip ...
- POJ2528Mayor's posters[线段树 离散化]
Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 59683 Accepted: 17296 ...
- HDU 3333 | Codeforces 703D 树状数组、离散化
HDU 3333:http://acm.hdu.edu.cn/showproblem.php?pid=3333 这两个题是类似的,都是离线处理查询,对每次查询的区间的右端点进行排序.这里我们需要离散化 ...
- HDU 3743 Frosh Week (线段树+离散化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3743 Frosh Week Time Limit : 2000/1000ms (Java/Other) ...
- Hihocoder 1079 离散化
离散化这里有很多种方式 利用结构体记录最初的索引在按位置排序再记录排名即为离散的位置再按索引排回来 或者用数组记录排序后直接对原位置二分直接去找离散应在的位置 或者对数组排序后直接map 3 20 1 ...
- UVALive 7141 BombX(离散化+线段树)(2014 Asia Shanghai Regional Contest)
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...
随机推荐
- 对于for循环和while循环,两种形式的优缺点
1.for循环 一般用于知道循环次数,并且for循环可以节省内存以及代码简洁,在循环语句中定义一个局部变量,循环结束后,局部变量就被释放了. ;val<=;val++) { sum+=val; ...
- 【LeetCode 235_二叉搜索树】Lowest Common Ancestor of a Binary Search Tree
解法一:递归 TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if (root == NULL | ...
- fluent nhibernate映射的数值类型问题
fluent nhibernate中,数值类型设置不当,就可能会引发一些意想不到错误. 一.引发映射错误 比如,oracle数据库中,字段ID类型是number,结果用codesmith生成代码,实体 ...
- WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable(spark加载hadoop本地库的时候出现不能加载的情况要怎么解决呢?)
原文地址: https://www.zhihu.com/question/23974067/answer/26267153 原文内容: 我64位机器,当时hadoop启动的时候出现这个问题是因为had ...
- Adobe Flash Player - imsoft.cnblogs
Adobe Flash Player是一个跨平台.基于浏览器的应用程序.运行时,它可以跨屏幕和浏览器原汁原味地查看具有表现力的应用程序.内容和视频.Flash Player实现了移动屏幕上的高性能优化 ...
- 20155229 2016-2017-2 《Java程序设计》第八周学习总结
20155229 2016-2017-2 <Java程序设计>第八周学习总结 教材学习内容总结 第十四章 NIO使用频道(Channel)来衔接数据节点,在处理数据时,NIO可以设定缓冲区 ...
- HTML第二课——css【2】
请关注公众号:自动化测试实战 现在继续上一节课的内容,看下面代码: <!DOCTYPE html><html><head> <meta charset= ...
- (转)Linux 定时关机、休眠命令
立刻关机:sudo haltsudo init 0 sudo shutdown -h nowsudo shutdown -h 0....定时/延时关机:sudo shutdown -h 19:3019 ...
- MySQL--REPLACE INTO更新自增列值引发的异常
##=====================================================================##测试环境:MySQL版本:MySQL 5.7.19复制 ...
- day13 python学习 迭代器,生成器
1.可迭代:当我们打印 print(dir([1,2])) 在出现的结果中可以看到包含 '__iter__', 这个方法,#次协议叫做可迭代协议 包含'__iter__'方法的函数就是可迭代函数 ...