题目链接:http://poj.org/problem?id=3666
题意:有一个n个数的序列a,现在要把这些序列变成单调增的或者单调减的序列 b ,
其价值为|A1 - B1| + |A2 - B2| + ... + |AN - BN | 现在要让价值最小;
b序列表示为 a 的有序序列;
用dp[i][j]表示把前i - 1个数变成单调且最后一个数是b[j]的最小价值;
那么dp[i][j] = min(dp[i-1][k]) + abs(a[i]-b[j]);(1<= k <= j);
看似三层循环,但是求最小值的可以省略;
k<=j是因为,前i-1个数已经变成单调的了,要想第i个数也是单挑的,那么前i个数就要小于等于b[j];
题的数据可能比较水,只需求变成单挑递增的即可,否则还要倒着来一遍;
#include<iostream> #include<algorithm> #include<string.h> #include<stdio.h> #include<math.h> using namespace std; #define INF 0x3f3f3f3f #define N 2100 #define PI 4*atan(1.0) #define mod 110119 #define met(a, b) memset(a, b, sizeof(a)) typedef long long LL; int a[N], b[N], dp[N][N], n; int main() { while(scanf("%d", &n) != EOF) { for(int i=1; i<=n; i++) { scanf("%d", &a[i]); b[i] = a[i]; } sort(b+1, b+n+1); met(dp, 0); for(int i=1; i<=n; i++) { int Min = INF; for(int j=1; j<=n; j++) { Min = min(dp[i-1][j], Min); dp[i][j] = Min + abs(a[i]-b[j]); } } int ans = INF; for(int i=1; i<=n; i++) ans = min(ans, dp[n][i]); printf("%d\n", ans); } return 0; }
时间: 2024-11-03 21:47:03