要求:一个由正整数ai组成的长度为N数列,变成一个不增或不减数列所需的最小代价,一个数字变化1对应的代价为1。
数据范围:1 ≤ N ≤ 2,000,0 ≤ ai ≤ 1,000,000,000
方法:简单dp 离散化
1.ai太大了,因此需要离散化,假设求的是不减数列,将A数组从小到大排列为b数组。
1.dp[i][j]表示前i个数中最大数为b[j]的最小代价。
2.dp[i][j] = abs(b[j] - a[i]) + min(dp[i-1][k]) 1<=k<=j。这么写会T的,所以要一次找到min(dp[i-1][k]),可以遍历j的时候找到对应的k。
3.发现可以用滚动数组减掉i这一维。
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
#include<map>
#define inf 0x3f3f3f3f
using namespace std ;
int n ;
int a[2005] ;
int b[2005] ;
long long dp[2005] ;
int main()
{
int i , j , k ;
long long min1 , ans ;
scanf("%d" , &n) ;
for(i = 1 ; i <= n ; i ++)
{
scanf("%d" , &a[i]) ;
b[i] = a[i] ;
}
sort(b + 1 , b + n + 1) ;
memset(dp , 0 , sizeof(dp)) ;
ans = inf ;
for(i = 1 ; i <= n ; i ++)
{
min1 = inf ;
for(j = 1 ; j <= n ; j ++)
{
min1 = min(min1 , dp[j]) ;
dp[j] = abs(b[j] - a[i]) + min1 ;
}
}
for(i = 1 ; i <= n ; i ++)
ans = min(ans , dp[i]) ;
printf("%lld\n" , ans) ;
}