一道很棒的DP题目。
裸的DP方程很好搞:
$f[i][j]=min \{ f[i-1][k]+ C \times |k-j| +(k-a[i])^2 \}$
这个复杂度显然无法承受,考虑优化。
这个东西肯定不满足单调性和斜率上的优化条件,所以考虑分解这个式子。
$f[i][j]=min \{ f[i-1][k]+ C \times |j-k| +(k-a[i])^2 \}$
$f[i][j]=\begin{equation} \begin{cases} (j-a[i])^2+j \times C+min \{ f[i-1][k]-k\times C \} (k \leq j) \\ (j-a[i])^2-j \times C+min \{ f[i-1][k]+k\times C\} (j < k) \end{cases} \end{equation} $
然后把右边那两部分预处理一下就行了
//POJ 3612 //by Cydiater //2016.10.8 #include <iostream> #include <cstdlib> #include <queue> #include <map> #include <cstdio> #include <iomanip> #include <algorithm> #include <ctime> #include <cmath> #include <cstring> #include <string> using namespace std; #define ll long long #define up(i,j,n) for(int i=j;i<=n;i++) #define down(i,j,n) for(int i=j;i>=n;i--) const int MAXN=1e6+5; const int oo=0x3f3f3f3f; inline int read(){ char ch=getchar();int x=0,f=1; while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int N,C,height[MAXN],high[MAXN],f[MAXN],low[MAXN],ans=oo; namespace solution{ void init(){ N=read();C=read(); up(i,1,N)height[i]=read(); } void slove(){ memset(high,10,sizeof(high)); memset(low,10,sizeof(low)); up(i,1,100)f[i]=height[1]<=i?(i-height[1])*(i-height[1]):oo; up(i,2,N){ int tmp=oo; down(j,100,1)low[j]=tmp=min(tmp,f[j]+j*C);tmp=oo; up(j,1,100)high[j]=tmp=min(tmp,f[j]-j*C); up(j,1,100)f[j]=j<height[i]?oo:((j-height[i])*(j-height[i])+min(low[j]-j*C,high[j]+j*C)); } up(i,1,100)ans=min(ans,f[i]); } void output(){ cout<<ans<<endl; } } int main(){ //freopen("input.in","r",stdin); using namespace solution; init(); slove(); output(); return 0; }