OMG愛喫雞
Time Limit: 3000ms
Memory Limit: 65536KB
Description
dp[i][j]表示前i爲,最後一位爲j的情況,因爲數字只有2000個,且最後一位修改的值一定2000個數字中出現過的一個,枚舉最後一位數字,dp遞推一下即可
注意:遞推時用minv[i][j]表示前i個以j結尾的最小的值是多少,這樣遞推時只需要o(1)便可只前面最優的值,直接遞推即可(遞推和優化),這樣o(n^2)即可解。
ps(最後結果最大值會超過0x3f3f3f3f,INF設成0x3f3f3f3f會WA)
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ms(x,y) memset(x,y,sizeof(x))
using namespace std;
typedef long long ll;
const int mod = 998244353;
const int maxn = 2010;
int a[maxn], b[maxn], p[maxn];
ll minv[maxn][maxn];
ll dp[maxn][maxn];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;
while (~scanf("%d", &n))
{
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]), b[i] = a[i];
sort(b + 1, b + 1 + n);
int tol = 2;
p[1] = b[1];
for (int i = 2; i <= n; i++)
{
if (b[i] != b[i - 1])
{
p[tol++] = b[i];
}
}
ms(dp, INF);
//ms(dp[0], 0);
ms(minv, INF);
ms(minv[0], 0);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j < tol; j++)
{
dp[i][j] = minv[i - 1][j] + abs(p[j] - a[i]);
minv[i][j] = min(minv[i][j - 1], dp[i][j]);
}
}
ll ans = dp[n][1];
for (int i = 1; i < tol; i++)
{
ans = min(ans, dp[n][i]);
}
printf("%lld\n", ans);
}
return 0;
}