Making the Grade 路面修整

2024-01-09 17:59
文章标签 路面 grade making 修整

本文主要是介绍Making the Grade 路面修整,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

「POJ 3666」Making the Grade 路面修整

1 算法标签

dp动态规划,滚动数组优化

2 题目难度

提高/提高+

3 题面

「POJ 3666」Making the Grade 路面修整

4 分析题面

4.1 简要描述

给出数列 A A A, 求非严格单调不上升或单调不下降, 且 S = ∑ i = 1 N ∣ A i − B i ∣ S=\sum^N_{i=1}|A_i-B_i| S=i=1NAiBi 最小的序列 B B B,输出 S S S

4.2 模型转换

输入N, 然后输入N个数,求最小的改动这些数使之成非严格递增或非严格递减即可

5 问题分析

以B为非严格单调递增为例

考虑已经选了 n n n个数

  • n = 1 n=1 n=1 A 1 = B 1 A_1=B_1 A1=B1 S S S最小为 ∣ A 1 − B 1 ∣ |A_1-B_1| A1B1

  • n > 1 n>1 n>1,前面已经选择了 n − 1 n-1 n1个数,取得了最小值,考虑怎么取第 n n n个数

    • A i ≥ B i − 1 A_i≥B_{i-1} AiBi1 B i = A i B_i=A_i Bi=Ai显然最优

    • A i < B i − 1 A_i<B_{i-1} Ai<Bi1

      • B i = A i B_i=A_i Bi=Ai

      • B k , B K + 1 , . . . , B i B_k,B_{K+1},...,B_i Bk,BK+1,...,Bi都赋值为 A k , A k + 1 , . . . , A i A_k,A_k+1,...,A_i Ak,Ak+1,...,Ai的中位数

        口胡证明:

        我们可以将 B k , B K + 1 , . . . , B i B_k,B_{K+1},...,B_i Bk,BK+1,...,Bi标记在数轴上,再将 A k , A k + 1 , . . . , A i A_k,A_k+1,...,A_i Ak,Ak+1,...,Ai标记上

        那么,其实 S S S的几何含义就是每一组 A i A_i Ai B i B_i Bi的距离之和

        我们也学过绝对值问题: ∣ x − k 1 ∣ + ∣ x − k 2 ∣ + ∣ x − k 3 ∣ . . . |x-k_1|+|x-k_2|+|x-k_3|... xk1+xk2+xk3...的最小值这种

        其实和这里的 S S S是没有任何区别的

        所以,我们知道零点分段法

        就是取中位数(就是使每个绝对值内部为0的x答案数组的中位数)

        可以使得绝对值之和最小

        1. 如果x在两个 k k k之间,那么无论x在哪,距离之和都是这两个k的距离
        2. 如果在这两个 k k k之外,那么距离之和则为两个k距离加上两倍的x距近的k的距离,肯定小于第一种情况

        那么我们只要尽量让 x x x在越多的 k k k之间即可

        那么最佳x在图中就是 4 4 4,如果 k k k的个数为偶数n,则是 k n / 2 k_{n/2} kn/2 K n / 2 + 1 K_{n/2+1} Kn/2+1之间

        综上,选择中位数最佳

通过综上分析,我们直接暴力肯定是不行的~~(这个复杂度直接爆掉了)~~

但是!

我们可以得到一个结论:

B数列中的每个数必定都为A数列中的元素

所以,我们可以考虑dp

阶段:到第 i i i

状态: d p i , j dp_{i,j} dpi,j表示以 B j B_j Bj结尾的 S m i n S_{min} Smin

B数组是A的复制排序处理过后的数组

d p [ i ] [ j ] dp[i][j] dp[i][j]表示把前i个数变成不严格单调递增且第 i i i个数变成原来第 j j j大的数的最小代价

转移方程: d p i , j = m i n ( d p i − 1 , j ) + ∣ A i − B j ∣ , 其 中 1 ≤ j ≤ n dp_{i,j}=min(dp_{i-1,j})+|A_i-B_j|,其中1≤j≤n dpi,j=min(dpi1,j)+AiBj,1jn

6 实现细节

6.1 滚动数组

开二维数组有点浪费欸

那怎么办呢?

由于我们只用到了 i − 1 i-1 i1

所以,我们考虑用滚动数组优化,用位运算符&来记录,这样就只用了 0 / 1 0/1 0/1来表示,重复利用,节省空间

i i i& 1 1 1的效果和 i i i% 2 2 2的效果是一样的,但是 i i i& 1 1 1要快一点

且这种方式比直接写0/1少了一个不断交换的过程

窝jio得这个还是很香的

i − > i i->i i>i & 1 1 1 i − 1 − > ( i − 1 ) i-1->(i-1) i1>(i1)& 1 1 1

方程就变成了这样:

d p [ i dp[i dp[i& 1 ] [ j ] = m i n ( d p [ ( i − 1 ) 1][j]=min(dp[(i-1) 1][j]=min(dp[(i1)& ] [ k ] ) + ∣ A [ i ] − B [ j ] ∣ , 其 中 1 ≤ j ≤ n , 1 ≤ k ≤ j ][k])+|A[i]-B[j]|,其中1≤j≤n,1≤k≤j ][k])+A[i]B[j],1jn,1kj

6.2 最小值

但是这个复杂度。。

看上去好像是3层循环,就是 O ( n 3 ) O(n^3) O(n3)

n < = 2000 n<=2000 n<=2000 的时候就已经game over了,显然不行啊

这个问题应该有手就行

其实只要一边更新 m i n ( f [ i − 1 ] [ k ] ) min(f[i-1][k]) min(f[i1][k])一般算当前的 f [ i ] [ j ] f[i][j] f[i][j]就行

(因为 k k k只到 j j j

6.3 降序

不严格单调不上升的情况也一样

更加方便的是可以把 B B B数组从大到小排序后,做单调不下降的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 总结

  1. 最大的收获:dp!!!

  2. 新鲜的知识:更优秀的滚动数组写法

  3. 相似的题目:CF #371 div.1 C Sonya and Problem Wihtout a Legend

这篇关于Making the Grade 路面修整的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/587960

相关文章

【POJ 3666】Making the Grade(简单DP)

首先可以明确一个方面,那就是如果将X改成Y,那么Y肯定是这N个数中的某一个(为什么仔细想想) 之后可以得到一个状态转移那就是dp[i][j]代表已经考虑了i位的情况下,结尾为j的最小更改数。 状态转移为dp[i][j] = min(dp[i-1][k] + abs(a[i] - b[j])) 这样的话可以写出一个初步的代码: #include<cstdio>#include<cst

[论文笔记]Making Large Language Models A Better Foundation For Dense Retrieval

引言 今天带来北京智源研究院(BAAI)团队带来的一篇关于如何微调LLM变成密集检索器的论文笔记——Making Large Language Models A Better Foundation For Dense Retrieval。 为了简单,下文中以翻译的口吻记录,比如替换"作者"为"我们"。 密集检索需要学习具有区分性的文本嵌入,以表示查询和文档之间的语义关系。考虑到大语言模

【ZOJ】3889 Making Sequence【构造】

传送门:【ZOJ】3889 Making Sequence 根据题意构造即可。ZOJ月赛我们抢的第二个FBwww my  code: my~~code: #include <bits/stdc++.h>using namespace std ;typedef unsigned long long ULL ;const int MAXN = 205 ;ULL n , a , b , s ,

基于yolov8的路面垃圾检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv8的路面垃圾检测系统是一种利用深度学习技术实现的高效、精准的路面垃圾检测解决方案。该系统采用了YOLOv8目标检测算法,该算法在速度和精度上均表现出色,能够实时或近实时地检测路面上的垃圾。 系统通过训练YOLOv8模型,使其能够识别并定位多种类型的路面垃圾,如塑料袋、纸屑等。在实际应用中,系统可以支持图片、视频以及摄像头的输入,通过界面实时显示目标位置、检测结果、和

build.grade.kts 如何定义插件及插件扩展

定义插件和应用插件 在build.gradle.kts文件内 这里要注意的是,最后一行的Project扩展函数名必须要和上面apply方法里面create的参数一致,然后project扩展函数定义之前必须先apply<>()也就是先使用apply让plugin apply方法运行起来,才能创建到这个snowmanExtension扩展函数,才能在下面进行定义。否则会报错。这样就可以在别的地方使用

POJ 3666 Making the Grade (DP+离散化)

题目地址:POJ3666 dp[i][j]表示第i位时,值为j时的最小代价。因为j太大,由于要改变值的话,变到与之最近的值相同是最优的,所以可以离散化,这样,j对应了各个值得下标。复杂度O(n^2)。 代码如下: #include <iostream>#include <string.h>#include <math.h>#include <queue>#include <algor

开发一个python工具,pdf转图片,并且截成单个图片,然后修整没用的白边及循环遍历文件夹全量压缩图片

§ 今天推荐一键款本人开发的pdf转单张图片并截取没有用的白边工具 § 一、开发背景: 业务需要将一个pdf文件展示在前端显示,但是基于各种原因,放弃了h5使用插件展示 原因有多个,文件资源太大加载太慢、pdf展示兼容性问题、pdf展示效果不好、pdf字体有时缺失等等,所以将项目中的协议等,全部由pdf文档转成图片,因为文档太多,不可能找UI同学一个一个截图,所以我就基于python代码写了三

开发一个python工具,pdf转图片,并且截成单个图片,然后修整没用的白边

今天推荐一键款本人开发的pdf转单张图片并截取没有用的白边工具 一、开发背景: 业务需要将一个pdf文件展示在前端显示,但是基于各种原因,放弃了h5使用插件展示 原因有多个,文件资源太大加载太慢、pdf展示兼容性问题、pdf展示效果不好、pdf字体有时缺失等等,所以将项目中的协议等,全部由pdf文档转成图片,因为文档太多,不可能找UI同学一个一个截图,所以我就基于python代码写了三个工具。

英语学习笔记37——Making a bookcase

Making a bookcase 做书架 词汇 Vocabulary work v. 工作 ing形式:working 搭配:work on + 工作 做……工作    work for + 人 为……而工作 例句:我正在做我的家庭作业。    I am working on my homework.    我正在为Bobby工作。    I am working for Bobby. n.

hdu 5038 Grade

hdu 5038 Grade 给定一个计算公示 以及W的值 计算会出现多少种结果  主要是  输入n=1的时候 直接输出结果而不是BAD #include <cstdio>#include <iostream>#include <cstring>#include <cmath>#include <algorithm>#include <string.h>#include <stri