1、例题:Soliders
题意抽象:
将n个不同坐标的点以最小的步骤移动到一条直线上,并且每个点的横坐标满足连续。
即(x, y), (x+1, y), ..., (x+i, y), ..., (x+n-1, y)
问题分解:
可以分解成x, y方向分别移动,以致步骤最小。
所以,y方向只要求出中位数(本身就是一个中位数问题)就行了,接下来,需要解决的是x方向。
子问题解决:
x方向能否直接运用中位数问题求解呢?
显示不能——它不是简单求解到某一点的距离和最短,而是要(按照某一特定y坐标)进行连续排列。
思考能不能转化?
考虑最后的状态——(x, y), (x+1, y), ..., (x+i, y), ..., (x+n-1, y)。
我们能不能把n个横坐标移到x0, x1, x2, .. , xn-1 的问题转化到n个横坐标移动到一个点(x0)上呢。答案是:能!
首先,xi 到 x0 需要移动i步。我们先从n个横坐标中把这个i步代价减去(这是因为我们最终求解到的是到x0的最小距离,对于最终排好的x[i]多加了i步),那么这样就全部转成到x0一个点上的移动距离了。
这样,我们可以使用中位数问题求解了。
即:
for i <- 0 to n-1 do
x[i] <- x[i] - i
asceSort(x[i]);
注:中位数求解最小距离和有速度比较快的方法
for i <- 0 to n / 2 do
ans <- ans + x[n-1 - i] - x[i]
理由可以在坐标中上画图,一眼便知。