POJ 3666 简单dp 离散化

要求:一个由正整数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) ;  
}

猜你喜欢

转载自blog.csdn.net/Irving0323/article/details/85238767