Making the Grade POJ 3666(dp)

原题

题目链接

题目分析

有点难的dp,首先考虑一下对于第i个山坡,要使单调,不是把它改成跟上一个相等就是把它改成跟下一个相等,因此改完后的值肯定是原序列的一个值,首先考虑递增,先把原序列按从小到大排个序,把它当为b[i],然后对于原序列的每个数,考虑将它变为b[i]中的其中一个使得其花费最小,因此可以这样设置dp,dp[i][j]表示当前要改变的是第i个值,把它变为b[j]所需要的最小花费,更新如下.dp[i][j]=min(dp[i-1][k])(0<=k<=j),更新一遍,扫一下dp[n][j]找出最小值,令其为ans,然后对于递减序列,只需把b[i]从大到小排个序进行相同的操作即可,再从dp[n][j]和ans中找出最小值即为答案.题目有数据不够强,只考虑递增就能过了.

代码

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <utility>
 4 #include <cstdio>
 5 #include <cmath>
 6 #include <cstring>
 7 #include <string>
 8 #include <vector>
 9 #include <stack>
10 #include <queue>
11 #include <map>
12 #include <set>
13 
14 using namespace std;
15 typedef long long LL;
16 const int INF_INT=0x3f3f3f3f;
17 const LL INF_LL=0x3f3f3f3f3f3f3f3f;
18 
19 int a[3000],b[3000];
20 int dp[3000];
21 
22 int main()
23 {
24 //    freopen("black.in","r",stdin);
25 //    freopen("black.out","w",stdout);
26     int n;
27     cin>>n;
28     for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
29     sort(b+1,b+1+n);
30     for(int i=1;i<=n;i++)
31     {
32         int minn=INF_INT;
33         for(int j=1;j<=n;j++)
34         {
35             if(i==1) dp[j]=abs(b[j]-a[i]);
36             else
37             {
38                 minn=min(dp[j],minn);
39                 dp[j]=minn+abs(b[j]-a[i]);
40             }
41         }
42     }
43     int ans=INF_INT;
44     for(int i=1;i<=n;i++) ans=min(ans,dp[i]);
45     sort(b+1,b+1+n,greater<int>());
46     for(int i=1;i<=n;i++)
47     {
48         int minn=INF_INT;
49         for(int j=1;j<=n;j++)
50         {
51             if(i==1) dp[j]=abs(b[j]-a[i]);
52             else
53             {
54                 minn=min(dp[j],minn);
55                 dp[j]=minn+abs(b[j]-a[i]);
56             }
57         }
58     }
59     for(int i=1;i<=n;i++) ans=min(ans,dp[i]);
60     cout<<ans<<endl;
61     return 0;
62 }

猜你喜欢

转载自www.cnblogs.com/VBEL/p/11410825.html