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_i=\min_{j=1,a_j<a_i}^{i-1}(f_j+cost(j+1,i-1))
\]

边界:\(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\)的最小值,于是我们有

\[f[i][j]=\min_{k=1}^{j}(f[i-1][k])+|a_j-a_i|
\]

根据策略集合,显然这里可以维护前缀小,于是可以优化到\(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的更多相关文章

  1. 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 ...

  2. POJ 3666 Making the Grade

    Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more tha ...

  3. 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 ...

  4. POJ3666Making the Grade[DP 离散化 LIS相关]

    Making the Grade Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6445   Accepted: 2994 ...

  5. [CareerCup] 15.7 Student Grade 学生成绩

    15.7 Imagine a simple database storing information for students' grades. Design what this database m ...

  6. 英语语法 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 ...

  7. FPGA speed grade

    Altera的-6.-7.-8速度等级逆向排序,Xilinx速度等级正向排序. 不很严密地说,“序号越低,速度等级越高”这是Altera FPGA的排序方法, “序号越高,速度等级也越高”这是Xili ...

  8. HDU 5038 Grade(分级)

    Description 题目描述 Ted is a employee of Always Cook Mushroom (ACM). His boss Matt gives him a pack of ...

  9. hdu---(5038)Grade(胡搞)

    Grade Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Sub ...

  10. A-Making the Grade(POJ 3666)

    Making the Grade Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4656   Accepted: 2206 ...

随机推荐

  1. [转]gulp打包工具总结

    与grunt类似,gulp也是构建工具,但相比于grunt的频繁IO操作,gulp的流操作能更快更便捷地完成构建工作.gulp借鉴了Unix操作系统的管道(pipe)思想,前一级的输出,直接变成后一级 ...

  2. cordova 与 phonegap关系

    Apache Cordova是PhoneGap贡献给Apache后的开源项目,是从PhoneGap中抽出的核心代码,是驱动PhoneGap的核心引擎.PhoneGap是一个开源的开发框架,使用HTML ...

  3. Apache负载均衡

    Apache负载均衡 Apache也是可以实现负载均衡的.Apache的负载均衡主要是通过mod_proxy_balancer实现的.那么,apache负载均衡的配置方法是什么样的? 在apache的 ...

  4. taskFactory

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  5. 剑指offer——14机器人的运动范围

    题目描述 地上有一个m行和n列的方格.一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子. 例如,当k为18时,机器人能 ...

  6. jquery网页定位导航特效

    <!DOCTYPE html> <html lang="en"> <head> <script src="http://code ...

  7. scrapy的使用-scrapy shell

    进入     该目录下执行scrapy shell 文件, 在命令行可执行该文件中链接的xpath语法,和BeautifulSoup语法.

  8. JDBC_事务说明

    JDBC控制事务:1.事务:一个包含多个步骤的业务操作,如果这个业务操作被事务管理则多个步骤同时成功或同时失败2.操作: 1.开启事务 2.提交事务 3.回滚事务3.使用Connection对象来管理 ...

  9. scrapy不抓取重复的网页解决办法

    1.scrapy爬虫遇到一个问题,有时候会对一个网页重复爬取提取不同的数据,这时候会发现,后面的那个重复爬取scrapy直接终止了. 原因: scrapy 的request逻辑里面  dont_fil ...

  10. iOS开发系列-NSDate

    NSDate API 获取当前时间 获取时间戳 创建间隔指定时间戳的Date // 获取昨天 NSTimeInterval time = 24 * 60 * 60; NSDate *date = [N ...