#(离散化基础)知识扩展:利用离散化原理进行算法优化

(大量内容来自百度)

离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。例如:
原数据:1,999,100000,15;处理后:1,3,4,2;
原数据:{100,200},{20,50000},{1,400};
处理后:{3,4},{2,6},{1,5};

 

离散化是程序设计中一个常用的技巧,它可以有效的降低时间复杂度。其基本思想就是在众多可能的情况中,只考虑需要用的值。离散化可以改进一个低效的算法,甚至实现根本不可能实现的算法。要掌握这个思想,必须从大量的题目中理解此方法的特点。例如,在建造线段树空间不够的情况下,可以考虑离散化。
 
 

例1

给定平面上n个点的坐标,求能够覆盖所有这些点的最小矩形面积。其中,矩形可以倾斜放置,边不必平行于坐标轴
UVA10173UVA10173 [2]
这里的倾斜放置很不好处理,因为我们不知道这个矩形最终会倾斜多少度。假设我们知道这个矩形的倾角是α,那么答案就很简单了:矩形面积最小时四条边一定都挨着某个点。也就是说,四条边的斜率已经都知道了的话,只需要让这些边从外面不断逼近这个点集直到碰到了某个点。你不必知道这个具体应该怎么实现,只需要理解这可以通过某种方法计算出来,毕竟重点在下面的过程。
我们的算法很显然了:枚举矩形的倾角,对于每一个倾角,我们都能计算出最小的矩形面积,最后取一个最小值。
这个算法是否是正确的呢?我们不能说它是否正确,因为它根本不可能实现。矩形的倾角是一个实数,它有无数种可能,你永远不可能枚举每一种情况。我们说,矩形的倾角是一个“连续的”变量,它是我们无法枚举这个倾角的根本原因。我们需要一种方法,把这个“连续的”变量变成一个一个的值,变成一个“离散的”变量。这个过程也就是所谓的离散化。
我们可以证明,最小面积的矩形不但要求四条边上都有一个点,而且还要求至少一条边上有两个或两个以上的点。试想,如果每条边上都只有一个点,则我们总可以把这个矩形旋转一点使得这个矩形变“松”,从而有余地得到更小的矩形。于是我们发现,矩形的某条边的斜率必然与某两点的连线相同。如果我们计算出了所有过两点的直线的倾角,那么α的取值只有可能是这些倾角或它减去90度后的角(直线按“\”方向倾斜时)这么C(n,2)种。我们说,这个“倾角”已经被我们“离散化”了。
 离散化链接:
https://blog.csdn.net/xiangaccepted/article/details/73276826
https://www.cnblogs.com/sun-of-Ice/p/9419857.html
实例代码:
int n, a[maxn], t[maxn]; //这里以下标1为序列的起点,一般情况下从0开始也可以 for(int i = 1;i <= n;i++) { scanf("%d", &a[i]); t[i] = a[i];//t是一个临时数组,用来得到离散化的映射关系 } //下面使用了STL中的sort(排序),unique(去重),lower_bound(查找)函数 sort(t + 1, t + n + 1);//排序 int m = unique(t + 1, t + 1 + n) - t - 1;//去重,并获得去重后的长度m for(int i = 1;i <= n;i++) { a[i] = lower_bound(t + 1, t + 1 + m, a[i]) - t;//通过二分查找,快速地把元素和映射对应起来 }
posted @ 2019-08-28 10:06  会飞的字符串  阅读(597)  评论(0编辑  收藏  举报