poj3612Telephone Wire<DP>

链接:http://poj.org/problem?id=3612

题意:

有N根柱子, 高度确定, 现在要使它们连接起来,划分为相邻的柱子的高度差 h *C, 还可以加高度, 花费为所加高度 x 的平方;求最小花费;

思路:

朴素的想法: 用dp[i][j] 代表第 i 根柱子高度为 j 时的最小花费, 那么 dp[i][j] = dp[i-1][k] + abs( j-k ) * C + (j-a[i])^2;

复杂度为 10^5*10^2*10^2 = 10^9  TLE 无压力 ;

再来看上面的式子, 去绝对值得到  dp[i][j]=dp[i][k]+(j-k)*C+j-a[i]^2 = dp[i][k]-K*C+j*C+( j-a[i] )^2; ( j>k )

                dp[i][j]=dp[i][k]+(k-j)*C+j-a[i]^2 = dp[i][k]+K*C-j*C+( j-a[i] )^2; ( j<K)   

对于 j 来说 j*C+( j-a[i] )^2 为定值 所以我们只要考虑 dp[i][k]-K*C ( j>K ) 和 dp[i][k] + K*C (j<K)

我们可以用另外两个数组分别保存他们的最优解, 即可得到 dp 的最优解 ;

low[i-1][k]=dp[i - 1][k] - c * k   ;  high[i - 1][k] = dp[i - 1][k] + c * k ;

对于相同的 i, 它们都只与当前的k有关, 且可以互相转化,所以可以只开一维;

则 : dp[i][j] = min(low[i - 1][k] + c * j + (j - a[i]) ^ 2)  , high[i - 1][k] - c * j + (j - a[i]) ^ 2));

View Code
 1 #include<cstdio>
 2  #include<algorithm>
 3  #include<cstring>
 4  using namespace std;
 5  int dp[102],low[102],high[102];
 6  const int inf=1<<30;
 7  
 8  int main()
 9  {
10      int n,c;
11      while(scanf("%d%d",&n,&c)!=EOF){
12          int h;
13          memset(low,0x3f,sizeof(low));
14          memset(high,0x3f,sizeof(high));
15          
16          for(int i=1; i<=n; i++){
17             scanf("%d",&h);
18             if( i==1 ){
19                 for(int i=0; i<h; i++)
20                      dp[i]=inf;
21                  for(int i=h; i<=100; i++)
22                      dp[i]=(i-h)*(i-h);
23             }
24             else{
25                 memset(dp,0x3f,sizeof(dp));
26                  for(int j=h; j<=100; j++)
27                     dp[j]=min(j*c+(h-j)*(h-j)+low[j],(h-j)*(h-j)-j*c+high[j]);
28             }
29             
30              low[0]=dp[0];
31              for(int i=1; i<=100; i++)
32                  low[i]=min(dp[i]-i*c,low[i-1]);
33              high[100]=dp[100]+100*c;
34              for(int i=99; i>=0; i--)
35                  high[i]=min(dp[i]+i*c,high[i+1]);     
36          }
37          int ans=inf;
38          for(int i=0;i<=100;i++)
39              ans=min(ans,dp[i]);
40          printf("%d\n",ans);
41      }
42      return 0;
43  }
原文地址:https://www.cnblogs.com/jian1573/p/2853048.html