标签:std 朴素 class 理解 取值 规划 ems bsp 突破口
题目链接:http://poj.org/problem?id=3666
题意:农夫约翰想修一条尽量平缓的路,路的每一段海拔是A_i,修理后是B_i,花费|A_i – B_i|,求最小花费。平缓的意思是海拔单调增或单调减(非严格)
思路:
这是一道动态规划的问题,突破口是:每个数最后必然是原序列中的数。
用dp[i][j]表示:前i个数构成的序列,这个序列最大值为j,dp[i][j]的值代表相应的cost。
状态转移方程:dp[i][j]=abs(j-w[i])+min(dp[i-1][k]) (k<=j)
网上很多都是说用离散化的思想,但是一直不是很理解这是什么意思,就是将序列排序一下,然后用位置的前后关系来制定其值,这样时间复杂度变成O(N^2).
不是很理解别人的思路,我就想的朴素一点,大概就是把for 循坏 j 的数值的取值范围缩小一些
ac代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #define MAX_N 2005 using namespace std; typedef long long ll; ll a[MAX_N],b[MAX_N]; ll dp[MAX_N][MAX_N]; int n; int main(void){ while(~scanf("%d",&n)){ memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); b[i]=a[i]; } sort(b+1,b+n+1); for(int i=1;i<=n;i++){ ll mn=dp[i-1][1]; for(int j=1;j<=n;j++){ mn=min(mn,dp[i-1][j]); dp[i][j]=abs(a[i]-b[j])+mn; } } ll ans=dp[n][1]; for(int i=2;i<=n;i++) ans=min(ans,dp[n][i]); printf("%lld\n",ans); } return 0; }
标签:std 朴素 class 理解 取值 规划 ems bsp 突破口
原文地址:https://www.cnblogs.com/jaszzz/p/12685454.html