题意:n个序列,权值为相邻差值的绝对值之和*c。可以给每个数添加一个x,代价为x*x。求最小权。
题解:dp[i][j]为第i个数为j时的最小代价,转移时分两种情况,如果i-1的高度小于j,那么dp[i][j]=dp[i-1][k]+(a[i]-j)^2+(j-k)*c=(a[i]-j)^2+j*c+(dp[i-1][k]-k*c),记录所有小于j的dp[i-1][k]-k*c最小值为low[j],转移复杂度就变成1了,如果i-1高度不低于j,也同上,只是将-k*c改成了+k*c,j*c变成-j*c
View Code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 int dp[2][102],low[102],high[102]; 6 const int inf=0x3f3f3f3f; 7 int main() 8 { 9 int n,c; 10 while(scanf("%d%d",&n,&c)!=EOF) 11 { 12 int a,b,h; 13 memset(low,0x3f,sizeof(low)); 14 memset(high,0x3f,sizeof(high)); 15 scanf("%d",&h); 16 for(int i=0; i<h; i++) 17 dp[0][i]=inf; 18 dp[0][h]=0; 19 for(int i=h+1; i<=100; i++) 20 dp[0][i]=(i-h)*(i-h); 21 low[0]=dp[0][0]; 22 for(int i=1; i<=100; i++) 23 low[i]=min(dp[0][i]-i*c,low[i-1]); 24 high[100]=dp[0][100]+100*c; 25 for(int i=99; i>=0; i--) 26 high[i]=min(dp[0][i]+i*c,high[i+1]); 27 for(int i=2; i<=n; i++) 28 { 29 a=i&1,b=a^1; 30 scanf("%d",&h); 31 memset(dp[b],0x3f,sizeof(dp[b])); 32 for(int j=h; j<=100; j++) 33 dp[b][j]=min(j*c+(h-j)*(h-j)+low[j],(h-j)*(h-j)-j*c+high[j]); 34 low[0]=dp[b][0]; 35 for(int i=1; i<=100; i++) 36 low[i]=min(dp[b][i]-i*c,low[i-1]); 37 high[100]=dp[b][100]+100*c; 38 for(int i=99; i>=0; i--) 39 high[i]=min(dp[b][i]+i*c,high[i+1]); 40 } 41 int ans=inf; 42 for(int i=0;i<=100;i++) 43 ans=min(ans,dp[b][i]); 44 printf("%d\n",ans); 45 } 46 return 0; 47 }