POJ 3666 簡單dp 離散化
阿新 • • 發佈:2019-01-07
要求:一個由正整數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) ; }