「POJ 3666」Making the Grade 路面修整 题解报告
作者:互联网
「POJ 3666」Making the Grade 路面修整
个人评价(一句话描述对这个题的情感)
灰常好!( ̄▽ ̄)"
1 算法标签
dp动态规划+滚动数组优化
2 题目难度
提高/提高+
CF rating:2300
3 题面
「POJ 3666」Making the Grade 路面修整
4 分析题面
4.1 简要描述
给出数列 \(A\), 求非严格单调不上升或单调不下降, 且\(S=\sum^N_{i=1}|A_i-B_i|\) 最小的序列\(B\),输出\(S\)
4.2 模型转换
输入\(N\), 然后输入\(N\)个数,求最小的改动这些数使之成非严格递增或非严格递减即可
5 问题分析
以B为非严格单调递增为例
5.0 暴力
我们直接当考虑已经选了\(n\)个数:
-
若\(n=1,A_1=B_1\)时S最小为\(|A_1-B_1|\)
-
若\(n>1\),前面已经选择了n-1个数,取得了最小值,考虑怎么取第n个数
-
若 \(A_i≥B_{i-1}\),\(B_i=A_i\)显然最优
-
若\(A_i< B_{i-1}\)
-
\(B_i=A_i\)
-
将\(B_k,B_{K+1},...,B_i\)都赋值为\(A_k,A_k+1,...,A_i\)的中位数
口胡证明:
我们可以将\(B_k,B_{K+1},...,B_i\)标记在数轴上
再将\(A_k,A_k+1,...,A_i\)标记上
那么,其实S的几何含义就是每一组\(A_i\)到\(B_i\)的距离之和
我们的
小学数学也学过绝对值最值问题:求\(|x-k_1|+|x-k_2|+|x-k_3|...\)的最小值
其实和这里的\(S\)是没有任何区别的
所以,我们知道零点分段法可以解决这类问题
就是取中位数(就是使每个绝对值内部为0的x答案数组的中位数)
可以使得绝对值之和最小
-
-
如果\(x\)在两个\(k\)之间,那么无论\(x\)在哪,距离之和都是这两个\(k\)的距离
-
如果在这两个\(k\)之外,那么距离之和则为两个\(k\)距离加上两倍的\(x\)距近的\(k\)的距离,肯定不会优于于第一种情况
那么我们只要尽量让\(x\)在越多的\(k\)之间即可
那么最佳解\(x\)在图中就是\(4\),如果\(k\)的个数为偶数\(n\),则是\(k_{n/2}和K_{n/2+1}\)之间
综上,选择中位数最佳
-
5.1 dp(动态规划)
通过综上分析(5.0中),我们直接暴力模拟肯定是不行的(这个复杂度直接爆掉了)
但是!
我们可以从中得到一个\(very\) \(important\)的结论:
\(B\)数列中的每个数必定都为\(A\)数列中的元素
所以,我们可以考虑用\(dp\)来解决:
阶段:到第\(i\)位
状态:\(dp_{i,j}\)表示以\(B_j\)结尾的\(S_{min}\)
B数组是A的复制排序处理过后的数组
$\space \space $ \(dp[i][j]\)表示把前i个数变成不严格单调递增且第\(i\)个数变成原来第\(j\)大的数的最小代价
转移方程:\(dp_{i,j}=min(dp_{i-1,k})+|A_i-B_j|,其中1≤j≤n,1≤k≤j\)
6 实现细节
6.1 dp(动态规划)
6.1.1 滚动数组
从我们的\(dp\)方程:\(dp_{i,j}=min(dp_{i-1,k})+|A_i-B_j|,其中1≤j≤n,1≤k≤j\)
灰常容易地阔以算出空间复杂度是\(O(n^2)\)
这个。。秉承着我们能省则省的原则
看到这个开二维数组\(O(n^2)\)的空间貌似有点浪费
那怎么去优化空间呢?
又由于我们的\(dp\)方程中只用到了\(i-1\)的信息
于是我们下意识地反应:
——用滚动数组优化!
\(\space \space\)用位运算符&来记录,这样就只用了\(0/1\)来表示
重复利用,节省空间
\(\space\space\space\space\) \(i\)&\(1\)的效果和\(i\)%\(2\)的效果是一样的,但是\(i\)&\(1\)要快一点
\(\space\space\space\space\) 且这种方式比直接写\(0/1\)少了一个不断交换的过程
\(\space\space\space\space\) 窝jio得这个东西还是很·····香的
将\(i->i\) & \(1\),\(i-1->(i-1)\)&\(1\)
方程就变成了这样:
\(dp[i\)&\(1][j]=min(dp[(i-1)\)&\(][k])+|A[i]-B[j]|,其中1≤j≤n,1≤k≤j\)
6.1.2 最小值
但是这个复杂度。。
看上去好像是3层循环,就是\(O(n^3)\)啊
在\(n<=2000\) 的时候就已经\(game\space over\)了,显然不行啊
这个xiao问题应该有手就行吧
其实只要一边更新\(min(f[i-1][k])\)一般算当前的\(f[i][j]\)就行
(因为\(k\)只到\(j\))
6.1.3 降序
不严格单调不上升的情况也一样
更加方便的是可以把\(B\)数组从大到小排序后,做单调不下降的dp就
标签:...,3666,6.1,space,Grade,题解,个数,数组,dp 来源: https://www.cnblogs.com/Aurora1217/p/16347584.html