poj 3666 河南省第七届程序设计D题(山区修路)

题目大意:

给定一个序列,以最小代价将其变成单调不增或单调不减序列,求最小的变动价值;需要用到离散化dp

状态转移方程:

dp[i][j]=abs(j-w[i])+min(dp[i-1][k]);(k<=j)这里的k无需从1遍历到j。

只要在对j进行for循环的时候不断更新一个dp[i-1][j]的最小值mn=min(mn,dp[i-1][j]),

然后对dp[i][j]=abs(j-w[i])+mn即可;

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 const int N = 550;
 8 const int MAX = 0x3fffffff;
 9 long long dp[N][N];
10 int a[N],b[N],n;
11 int cmp(int x,int y)
12 {
13     if(x>y) return 1;
14     return 0;
15 }
16 long long  solve()
17 {
18     for(int i=1; i<=n; i++)
19     {
20      long long mn = dp[i-1][1];
21        for(int k =1; k<=n; k++)
22       {
23         mn = min(mn,dp[i-1][k]);
24         dp[i][k] = abs(a[i]-b[k])+mn;
25       }
26     }
27       long long ans = dp[n][1];
28       for(int i =1; i<=n; i++)
29       {
30         ans = min(ans,dp[n][i]);
31       }
32       return ans;
33 }
34 int main()
35 {
36     int T;
37     scanf("%d
",&T);//poj这个地方不是T组数据,需要改动输入
38     while(T--)
39     {
40         scanf("%d",&n);
41         for(int i = 1; i<=n; i++)
42         {
43             scanf("%d",&a[i]);
44             b[i] = a[i];
45         }
46     sort(b+1,b+n+1);
47     long long ans1 = solve();//一次递增序列
48     sort(b+1,b+1+n,cmp);
49     long long ans2 = solve();//一次递减序列求最小值
50     long long ans=min(ans1,ans2);
51     printf("%lld
",ans);
52     }
53     return 0;
54 }
原文地址:https://www.cnblogs.com/lovychen/p/4425058.html