原题
题目分析
有点难的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 }