Making the Grade
Making the Grade
https://ac.nowcoder.com/acm/problem/108263
题意:给定长度为的序列
,构造一个长度为
的序列
,满足:
非严格单调,即
不递增或者不递减。
- 最小化
思路:
这题数据弱,只考虑不递减的情况就可以过,但还要考虑
不递增的情况比如我代码中的数据。
引理:
在满足最小化的前提下,一定存在一种构造序列
的方案,使得
中的数值都在
中出现过。
状态表示在完成前
个数的构造时,
,那么转移方程就是:
当然可以通过排序的方式对数组A进行简单的离散化来降低复杂度
MyCode:
#include <iostream>
#include <cstdio>
#include<algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int maxn=2e3+7,maxm=2e5+7,mod=1e9+7;
typedef long long int ll;
typedef unsigned long long ull;
int a[maxn],b[maxn];
int f[maxn][maxn];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
for(int i=1; i<=n; ++i) {
cin>>a[i];
b[i]=a[i];
}
sort(b+1,b+1+n);
for(int i=1; i<=n; ++i) {
int val=1e9;
for(int j=1; j<=n; ++j) {
val=min(val,f[i-1][j]+abs(a[i]-b[j]));
f[i][j]=val;
}
}
int ans=1e9;
for(int i=1;i<=n;++i) ans=min(ans,f[n][i]);
for(int i=1; i<=n; ++i) {
int val=1e9;
for(int j=n; j; --j) {
val=min(val,f[i-1][j]+abs(a[i]-b[j]));
f[i][j]=val;
}
}
for(int i=1;i<=n;++i) ans=min(ans,f[n][i]);
cout<<ans<<'\n';
return 0;
}
/*
7
9 3 5 4 2 3 1
*/ 动态规划入门 文章被收录于专栏
能采用动态规划求解一般要具有3个性质: (1) 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。 (2) 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。 (3)有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(体现DP的优点)