描述
题解
每次看到 dp 问题都能知道是 dp,可是就是反应不过来如何 dp。
这次也是这样,找了找题解,算是搞明白怎么 dp 了。
根据题意我们可以知道,不管怎么调整,我们都可以通过把路的高度调整为一个已有的高度来实现结果最优。所以我们可以设,dp[i][j] 表示考虑到第 i 段数路时,将其高度调整为第 j 高度时的最优解。这样就好了,代码很容易理解,直接看代码吧。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAXN = 520;
const int INF = 0x3f3f3f3f;
int a[MAXN], b[MAXN], dp[MAXN][MAXN];
int main()
{
int T;
cin >> T;
int n;
while (T--)
{
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(dp, 0, sizeof(dp));
cin >> n;
for (int i = 0; i < n; i++)
{
scanf("%d", a + i);
b[i] = a[i];
}
sort(b, b + n);
for (int i = 0; i < n; i++)
{
int tmp = INF;
for (int j = 0; j < n; j++)
{
for (int k = 0; k <= j; k++)
{
tmp = min(tmp, dp[i][k]);
}
dp[i + 1][j] = tmp + abs(b[j] - a[i]);
}
}
int res = INF;
for (int i = 0; i < n; i++)
{
res = min(res, dp[n][i]);
}
reverse(a, a + n);
for (int i = 0; i < n; i++)
{
int tmp = INF;
for (int j = 0; j < n; j++)
{
for (int k = 0; k <= j; k++)
{
tmp = min(tmp, dp[i][k]);
}
dp[i + 1][j] = tmp + abs(b[j] - a[i]);
}
}
int res_ = INF;
for (int i = 0; i < n; i++)
{
res_ = min(res_, dp[n][i]);
}
printf("%d\n", min(res, res_));
}
return 0;
}