「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 简要描述
给出数列 , 求非严格单调不上升或单调不下降, 且 最小的序列,输出
4.2 模型转换
输入, 然后输入个数,求最小的改动这些数使之成非严格递增或非严格递减即可
5 问题分析
以B为非严格单调递增为例
5.0 暴力
我们直接当考虑已经选了个数:
-
若时S最小为
-
若,前面已经选择了n-1个数,取得了最小值,考虑怎么取第n个数
-
若 ,显然最优
-
若
-
-
将都赋值为的中位数
口胡证明:
我们可以将标记在数轴上
再将标记上
那么,其实S的几何含义就是每一组到的距离之和
我们的
小学数学也学过绝对值最值问题:求的最小值
其实和这里的是没有任何区别的
所以,我们知道零点分段法可以解决这类问题
就是取中位数(就是使每个绝对值内部为0的x答案数组的中位数)
可以使得绝对值之和最小
-
-
如果在两个之间,那么无论在哪,距离之和都是这两个的距离
-
如果在这两个之外,那么距离之和则为两个距离加上两倍的距近的的距离,肯定不会优于于第一种情况
那么我们只要尽量让在越多的之间即可
那么最佳解在图中就是,如果的个数为偶数,则是之间
综上,选择中位数最佳
-
5.1 dp(动态规划)
通过综上分析(5.0中),我们直接暴力模拟肯定是不行的(这个复杂度直接爆掉了)
但是!
我们可以从中得到一个 的结论:
数列中的每个数必定都为数列中的元素
所以,我们可以考虑用来解决:
阶段:到第位
状态:表示以结尾的
B数组是A的复制排序处理过后的数组
表示把前i个数变成不严格单调递增且第个数变成原来第大的数的最小代价
转移方程:
6 实现细节
6.1 dp(动态规划)
6.1.1 滚动数组
从我们的方程:
灰常容易地阔以算出空间复杂度是
这个。。秉承着我们能省则省的原则
看到这个开二维数组的空间貌似有点浪费
那怎么去优化空间呢?
又由于我们的方程中只用到了的信息
于是我们下意识地反应:
——用滚动数组优化!
用位运算符&来记录,这样就只用了来表示
重复利用,节省空间
&的效果和%的效果是一样的,但是&要快一点
且这种方式比直接写少了一个不断交换的过程
窝jio得这个东西还是很·····香的
将 & ,&
方程就变成了这样:
&&
6.1.2 最小值
但是这个复杂度。。
看上去好像是3层循环,就是啊
在 的时候就已经了,显然不行啊
这个xiao问题应该有手就行吧
其实只要一边更新一般算当前的就行
(因为只到)
6.1.3 降序
不严格单调不上升的情况也一样
更加方便的是可以把数组从大到小排序后,做单调不下降的dp就🆗了
6.1.4 时间复杂度
二维DP,所以就是
7 代码实现
#include<bits/stdc++.h>
using namespace std;
const int N=2e4+2;
int n,f[2][N],a[N],b[N],ans=0x3f3f3f3f;
bool cmp1(int x,int y){
return x<y;
}//升序
bool cmp2(int x,int y){
return x>y;
}//降序
void work(){
for(int i=1;i<=n;i++){
f[1][i]=abs(a[1]-b[i]);
}//边界条件
for(int i=2;i<=n;i++){
int minn=f[(i-1)&1][1];
for(int j=1;j<=n;j++){
minn=min(minn,f[(i-1)&1][j]);//边更新边求
f[i&1][j]=minn+abs(a[i]-b[j]);
//滚动数组
}
}
for(int i=1;i<=n;i++){
ans=min(ans,f[n&1][i]);
}//求答案
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];//拷贝到b数组
}
sort(b+1,b+1+n,cmp1);//从小到大
work(); //dp计算
sort(b+1,b+1+n,cmp2);//从大到小
work();//直接就是一样的啊
printf("%d",ans);//输出最小
return 0;
}
8 总结
-
最大的收获:就算做不出来也需要想一些可能的做法,说不定就撞对了
-
新鲜的知识:更优秀的滚动数组写法
-
相似的题目:CF #371 div.1 C Sonya and Problem Wihtout a Legend
本文作者:Yvette的博客
本文链接:https://www.cnblogs.com/yvette1217/p/16347584.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步