//https://www.luogu.com.cn/problem/P2893
#include<bits/stdc++.h>
#include<unordered_map>
#include<array>
#define ll long long
#define ull unsigned long long
#define all(a) a.begin(),a.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-8;
const ll mod = 1e9 + 7;
const int N = 2e3 + 5;
ll n, cost[N][N], a[N], min_cost[N][N];//cost[i][j]:第i个选第j大数字时的最小花费
/*
cost[i][j] = min(cost[i-1][k]+abs(a[i]-v[j]), cost[i][j]),k <= j此转移方程复杂度为n^3
我们发现cost[i-1][k]可在i-1出直接记录,所以复杂度为n^2
*/
void solve()//一定存在一种方案使得修改后的高度都是原来高度中的值
{
cin >> n;
vector<ll> v;
for (int i = 1; i <= n; i++)
cin >> a[i], v.push_back(a[i]);
sort(all(v));
v.erase(unique(all(v)), v.end());
for (int i = 1; i <= n; i++)//上升
{
for (int j = 0; j < v.size(); j++)
{
cost[i][j] = min_cost[i - 1][j] + abs(a[i] - v[j]);
if (j)
min_cost[i][j] = min(cost[i][j], min_cost[i][j - 1]);
else
min_cost[i][j] = cost[i][j];
}
}
ll ans1 = INF;
for (int i = 0; i < v.size(); i++)
ans1 = min(ans1, cost[n][i]);
for (int i = 1; i <= n; i++)//下降
{
for (int j = v.size() - 1; j >= 0; j--)
{
cost[i][j] = min_cost[i - 1][j] + abs(a[i] - v[j]);
if (j != v.size() - 1)
min_cost[i][j] = min(cost[i][j], min_cost[i][j + 1]);
else
min_cost[i][j] = cost[i][j];
}
}
ll ans2 = INF;
for (int i = 0; i < v.size(); i++)
ans2 = min(ans1, cost[n][i]);
cout << min(ans1, ans2) << '\n';
}
signed main()
{
IOS;
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
P2893 [USACO08FEB] Making the Grade G,dp10
于 2022-09-09 12:18:29 首次发布