题目描述
输入
-
Line 1: Two space-separated integers: N and C
- Lines 2..N+1: Line i+1 contains a single integer: heighti
输出
- Line 1: The minimum total amount of money that it will cost Farmer John to attach the new telephone wire.
样例输入
样例输出
f[i][j]表示前i根电线杆第i根高度为j是的最小费用
f[i][j]=min(f[i-1][k]+c*abs(k-j))+(j-h[i])^2
决策单调性:假设f[i][j-1]在k1时取最优,f[i][j]在k2时取最优,k2>=k1
可用go变量记录f[i][j-1]取最优值的位置,计算f[i][j]时从go开始枚举
令函数p(k)=(f[i-1][k]+c*abs(k-j))
p(k)是一个凹函数(随着k递增,p(k)先下降,后迅速上升)或者是单调递增函数
当p(k+1)>p(k)时,直接break,后面不存在更优的解
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,c,maxh,h[100001],f[100001][101],go; 7 int main() 8 {int i,j,l; 9 //freopen("file.in","r",stdin); 10 cin>>n>>c; 11 for (i=1;i<=n;i++) 12 { 13 scanf("%d",&h[i]); 14 maxh=max(maxh,h[i]); 15 } 16 memset(f,127/3,sizeof(f)); 17 for (i=h[1];i<=maxh;i++) 18 f[1][i]=(h[1]-i)*(h[1]-i); 19 for (i=2;i<=n;i++) 20 { 21 go=h[i-1]; 22 for (j=h[i];j<=maxh;j++) 23 { 24 int tmp=(j-h[i])*(j-h[i]); 25 int pre=2e9; 26 for (l=go;l<=maxh;l++) 27 { 28 int tmpp=f[i-1][l]+c*abs(j-l)+tmp; 29 if (tmpp<f[i][j]) 30 { 31 f[i][j]=tmpp; 32 go=l; 33 } 34 if (tmpp<pre) pre=tmpp; 35 else 36 break; 37 } 38 } 39 } 40 int ans=2e9; 41 for (i=h[n];i<=maxh;i++) 42 ans=min(ans,f[n][i]); 43 cout<<ans; 44 }