Making the Grade
给定长度为n的序列\(\{a_i\}\),求构造长度为n的递增序列\(\{b_i\}\),求\(\sum_{i=1}^n|a_i-b_i|\)最小值,\(1 ≤ N ≤ 2,000\)。
解
首先空间与时间不支持你表现\(b_i\)填什么,于是猜测\(b_i\)必然填的为\(a_i\)里的数。
证明:
显然填到第1个数满足条件,
假设前i-1个数满足条件,且为最优解。
考虑现在填到第i个数,如果\(a_i\geq b_{i-1}\),我们可以令\(b_i=a_i\)。
而如果\(a_i<b_{i-1}\),要么是\(b_i=b_{i-1}\)更优,要么得把\(b_i\)下调到x,同理前面的数也要下调,而此时必然有一段数\(b_i\)是等于x,因为如果还可以下调达到更优,之前就可以这么做了,而这一段达到最优可以是这一段对应的\(a_i\)的中位数,所以无论如何,都满足题意,故成立。
法一:
考虑到\(b_i\)中含有\(a_i\)的段性,故设\(f_i\)表示考虑到\(b_i\),且\(b_i=a_i\)的所求最小值,设\(cost(j+1,i-1)\)表示i,j间填左边填一段\(a_j\),右边填一段\(a_i\)的最小值,于是我们有
\]
边界:\(f_0=0\)其余无限大
答案:\(\min_{i=1}^n(f_i+\sum_{j=i+1}^n|a_j-a_i|)\)
至于cost如何求,你只要维护分别维护只填\(a_i\)或者\(a_j\)前缀和,枚举中间点转移即可,最终时间复杂度\(O(n^3)\)。
参考代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
#define intmax 0x7fffffff
using namespace std;
int A[2001],dp[2001],sl[2001],
sr[2001];
il void read(int&);
template<class free>il free Abs(free);
template<class free>il free Min(free,free);
int main(){
int n,i,j,k,l,ans(intmax);
memset(dp,66,sizeof(dp));
read(n),dp[1]=0;for(i=1;i<=n;++i){
read(A[i]);
for(j=1;j<i;++j){
if(A[j]>A[i])continue;
sl[j]=sr[j]=0,l=intmax;
for(k=j+1;k<i;++k)sl[k]=sl[k-1]+Abs(A[k]-A[j]);
for(k=j+1;k<i;++k)sr[k]=sr[k-1]+Abs(A[k]-A[i]);
for(k=j;k<i;++k)
l=Min(l,sl[k]-sl[j]+sr[i-1]-sr[k]);
dp[i]=Min(dp[i],dp[j]+l);
}
}
for(i=1;i<=n;++i){
j&=0;
for(k=i+1;k<=n;++k)
j+=Abs(A[k]-A[i]);
ans=Min(ans,j+dp[i]);
}printf("%d",ans);
return 0;
}
template<class free>
il free Min(free a,free b){
return a<b?a:b;
}
template<class free>
il free Abs(free x){
return x<0?-x:x;
}
il void read(int &x){
x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}
法二:
最直接的感觉是要想维护递增,我必然要表现出这里填什么,预处理\(c_i\)为\(a_i\)从小到大的数组,于是设\(f[i][j]\)表示处理到\(b_i\),这里令\(b_i=c_j\)的最小值,于是我们有
\]
根据策略集合,显然这里可以维护前缀小,于是可以优化到\(O(n^2)\)。
参考代码
#include <functional>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
#define intmax 0x7fffffff
using namespace std;
int A[2001],B[2001],
dp[2001][2001],opt[2001];
il void read(int&);
template<class free>
il free Abs(free);
template<class free>
il free Min(free,free);
int main(){
int n,i,j;read(n);
for(i=1;i<=n;++i)read(A[i]),B[i]=A[i];
sort(B+1,B+n+1);
for(i=1;i<=n;++i){
for(j=1;j<=n;++j)
dp[i][j]=Abs(A[i]-B[j])+opt[j];
opt[1]=dp[i][1];
for(j=2;j<=n;++j)opt[j]=Min(opt[j-1],dp[i][j]);
}int ans(intmax);
for(i=1;i<=n;++i)ans=Min(ans,dp[n][i]);
sort(B+1,B+n+1,greater<int>());
for(i=1;i<=n;++i){
for(j=1;j<=n;++j)
dp[i][j]=Abs(A[i]-B[j])+opt[j];
opt[1]=dp[i][1];
for(j=2;j<=n;++j)opt[j]=Min(opt[j-1],dp[i][j]);
}for(i=1;i<=n;++i)ans=Min(ans,dp[n][i]);
printf("%d",ans);
return 0;
}
template<class free>
il free Min(free a,free b){
return a<b?a:b;
}
template<class free>
il free Abs(free x){
return x<0?-x:x;
}
il void read(int &x){
x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}
法三:
注意到绝对值解的移动性,故可以维护一个大根堆,如果加进去的数比大于等于堆顶,不管,如果小的话,就把这个数两次加进堆,ans累加堆顶-该数,再弹掉堆顶。
证明先放一放。
参考代码:
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <functional>
#define il inline
#define ri register
using namespace std;
priority_queue<int,vector<int>,less<int> >s;
priority_queue<int,vector<int>,greater<int> >b;
il void read(int&);
int main(){
int n,i,a;read(n);
int ans1(0),ans2(0);
read(a),s.push(a),b.push(a);
for(i=2;i<=n;++i){
read(a),s.push(a),b.push(a);
if(a<s.top())ans1+=s.top()-a,s.pop(),s.push(a);
if(a>b.top())ans2+=a-b.top(),b.pop(),b.push(a);
}printf("%d",ans1>ans2?ans2:ans1);
return 0;
}
il void read(int &x){
x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}
于是我们可以得到结论,递推随着状态优化,又可以转移时优化,但贪心显然排除了太多无用的状态,故是最好的优化方式。
Making the Grade的更多相关文章
- kaungbin_DP S (POJ 3666) Making the Grade
Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more tha ...
- POJ 3666 Making the Grade
Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more tha ...
- CF719C. Efim and Strange Grade[DP]
C. Efim and Strange Grade time limit per test 1 second memory limit per test 256 megabytes input sta ...
- POJ3666Making the Grade[DP 离散化 LIS相关]
Making the Grade Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6445 Accepted: 2994 ...
- [CareerCup] 15.7 Student Grade 学生成绩
15.7 Imagine a simple database storing information for students' grades. Design what this database m ...
- 英语语法 It all started the summer before second grade when our moving van pulled into her neighborhood
It all started the summer before second grade when our moving van pulled into herneighborhood It all ...
- FPGA speed grade
Altera的-6.-7.-8速度等级逆向排序,Xilinx速度等级正向排序. 不很严密地说,“序号越低,速度等级越高”这是Altera FPGA的排序方法, “序号越高,速度等级也越高”这是Xili ...
- HDU 5038 Grade(分级)
Description 题目描述 Ted is a employee of Always Cook Mushroom (ACM). His boss Matt gives him a pack of ...
- hdu---(5038)Grade(胡搞)
Grade Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Sub ...
- A-Making the Grade(POJ 3666)
Making the Grade Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4656 Accepted: 2206 ...
随机推荐
- csp-s模拟测试92
csp-s模拟测试92 关于$T1$:最短路这一定建边最短路. 关于$T2$:傻逼$Dp$这一定线段树优化$Dp$. 关于$T3$:最小生成树+树P+换跟一定是这样. 深入(?)思考$T1$:我是傻逼 ...
- 【python】collections的使用
老师布置了一个课后作业. 统计文本中字母出现的次数并找到最大的那一个 首先是读取文本吧.和c里的也差不多,打开,关闭,读取. path = f = f.close() 然后就用到了这个黑科技.coll ...
- vue 父子组件、兄弟组件传值
参考文章:Vue2.0子同级组件之间数据交互 1.父组件可以使用 props 把数据传给子组件.2.子组件可以使用 $emit 触发父组件的自定义事件. (一)父组件给子组件传值,关键字:props ...
- pointer && reference
关注点在于区别两者之间的不同. 我们可以从两者使用的场景进行区分: 1, 是否需要存在null的情况: YES-pointer NO-reference 如果确定不会存在null的情况,那么使用ref ...
- Maven + Springboot + redis 配置
前言 刚进入到Java 开发的世界,对于小白Java的我来说,使用Maven + SpringBoot 的项目下启动redis: 第一步 本地安装Redis 服务 关于redis的教程链接 点击这里: ...
- Linux课程---13、linux中任务计划介绍(任务计划分类)
Linux课程---13.linux中任务计划介绍(任务计划分类) 一.总结 一句话总结: 1.一次性任务计划:at 2.周期性任务计划:crontab 1.linux中如何添加一次性任务计划? at ...
- redis可视化客户端工具TreeNMS
TreeNMS是一款redis,Memcache可视化客户端工具,采用JAVA开发,实现基于WEB方式对Redis, Memcached数据库进行管理.维护. 功能包括:状态参数监控,NoSQL数据库 ...
- 如何有效管理Windows系统帐户权限
权限是Windows管理的基础,当然与Windows用户关系最密切,平时接触最多的是与帐户相关的权限.对于Windows帐户权限的管理,你是否完全了解呢?下面,笔者以Winsows XP为例进行相关测 ...
- iOS开发之SceneKit框架--SCNView.h
1.SCNView 在macOS中,SCNView是NSView的子类,在iOS和tvOS中,SCNView是UIView的子类.SCNView用于显示SceneKit的3D场景,而需要设置场景的相关 ...
- https://www.cnblogs.com/chinabin1993/p/9848720.html
转载:https://www.cnblogs.com/chinabin1993/p/9848720.html 这段时间一直在用vue写项目,vuex在项目中也会依葫芦画瓢使用,但是总有一种朦朦胧胧的感 ...