题目链接:http://poj.org/problem?id=3666
题意是给出一组数,每个数代表当前位置的地面高度,问把路径修成非递增或者非递减,需要花费的最小代价?
///用dp[i][j]表示:前i个数构成的序列,这个序列最大值为j,dp[i][j]的值代表相应的cost。
///dp[i][j]=abs(j-w[i])+min(dp[i-1][k]);(k<=j)
///i-1构成的序列,最大值是k + (j-w[i])变成此步需要的花费
因为要把路径修成非递减路径,所以a[j]>a[k],所以我们要三重循环来搞,时间复杂度O(n^3)。
如果我们对原来数列进行复制排序的话,a[j]>a[k]就转化为了j>k,这样就成功的把时间复杂度从O(n^3)降为O(n^2)。
空间复杂度也可以用滚动数组从O(n^2)变为O(n)。
#include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; #define N 2100 #define INF 0x3f3f3f3f #define met(a) memset(a, 0, sizeof(a)) //1061109567 0x3f3f3f3f //268435455 0xfffffff 本题用这个会错的;因为它不够大;害的我wa了那么多次-_-; int n, dp[N][N], a[N], b[N]; int main() { while(scanf("%d", &n)!=EOF) { met(a); met(b); for(int i=1; i<=n; i++) { scanf("%d", &a[i]); b[i] = a[i]; } sort(b+1, b+n+1); for(int i=1; i<=n; i++) { int Min = INF; for(int j=1; j<=n; j++) { Min=min(Min, dp[i-1][j]); 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 ", ans); } return 0; }