poj 3612 Telephone Wire

Description

Farmer John’s cows are getting restless about their poor telephone service; they want FJ to replace the old telephone wire with new, more efficient wire. The new wiring will utilize N (2 ≤ N ≤ 100,000) already-installed telephone poles, each with some heighti meters (1 ≤ heighti ≤ 100). The new wire will connect the tops of each pair of adjacent poles and will incur a penalty cost C × the two poles’ height difference for each section of wire where the poles are of different heights (1 ≤ C ≤ 100). The poles, of course, are in a certain sequence and can not be moved.
Farmer John figures that if he makes some poles taller he can reduce his penalties, though with some other additional cost. He can add an integer X number of meters to a pole at a cost of X2.
Help Farmer John determine the cheapest combination of growing pole heights and connecting wire so that the cows can get their new and improved service.

Input
* Line 1: Two space-separated integers: N and C
* Lines 2..N+1: Line i+1 contains a single integer: heighti

Output
* Line 1: The minimum total amount of money that it will cost Farmer John to attach the new telephone wire.

Sample Input
5 2
2
3
5
1
4

Sample Output
15

Source
USACO 2007 November Gold

题目大意:有n根柱子,要在相邻两根之间连接,花费为abs(h[i]-h[j])*c(c为输入时输入的花费),现在可以增加某根柱子的长度,求最少花费。

输入:第一行两个数n,c
接下来n行,每行一个数代表柱子的高度

首先我们先想到用dp,用dp[i][j]代表选到第i个时增加j个高度的总共最小花费,则答案就为min(dp[n][i])
递推式:dp[i][j]=min(dp[i-1][k]+(j-h[i])*(j-h[i])+c*abs(j-k))(h[i]代表第i个柱子的高度)
这样显然时间复杂度很大,但usaco的数据可以水过
代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<ios>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
#include<functional>
#include<bitset>
using namespace std;
const int maxn=100005,maxm=105,inf=1e9;
int dp[maxn][maxm],h[maxn];
int main(){
    freopen("telewire.in","r",stdin);
    freopen("telewire.out","w",stdout);
    int i,j,k,n,c,H=0;
    cin>>n>>c;
    for(i=1;i<=n;i++){
        scanf("%d",&h[i]);
        H=max(H,h[i]);
    }
    for(i=0;i<=H;i++)
        dp[0][i]=0;
    int ans=inf;
    for(i=1;i<=n;i++)
        for(j=h[i];j<=H;j++){
            dp[i][j]=inf;
            for(k=h[i-1];k<=H;k++)
                dp[i][j]=min(dp[i][j],dp[i-1][k]+(j-h[i])*(j-h[i])+c*abs(j-k));
        }
    for(i=h[n];i<=H;i++)
        ans=min(ans,dp[n][i]);
    printf("%d\n",ans);
    return 0;
}

我们可以发现abs(j-k)可以分为j大于k与j小于k两种情况
当j大于k时 dp[i][j]=min(dp[i-1][k]+(j-h[i])*(j-h[i])+c*abs(j-k))
=(j-h[i])*(j-h[i])+min(dp[i-1][k]+c*j-c*k)
=(j-h[i])*(j-h[i])+c*j+min(dp[i-1][k]-c*k)
当j大于k时 dp[i][j]=min(dp[i-1][k]+(j-h[i])*(j-h[i])+c*abs(j-k))
=(j-h[i])*(j-h[i])+min(dp[i-1][k]-c*j+c*k)
=(j-h[i])*(j-h[i])-c*j+min(dp[i-1][k]+c*k)
无论是dp[i-1][k]-c*k还是dp[i-1][k]+c*k都是与j无关的所以对于每个i我们可以分别记录这两个值。
我们记low[i]=min(dp[i-1][k]+c*k),high[i]=min(dp[i-1][k]-c*k)
于是dp[i][j]=(j-h[i])*(j-h[i])+min(low[i]-c*j,high[i]+c*j)
代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<ios>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
#include<functional>
#include<bitset>
using namespace std;
const int maxn=100000+10,maxm=100+10,inf=1e9;
int low[maxn],high[maxn],d[maxn];
int ans=inf;
int main(){
    int n,m,i,j,t,x;
    freopen("telewire.in","r",stdin);
    freopen("telewire.out","w",stdout);
    scanf("%d%d",&n,&m);
    scanf("%d",&x);
    for(i=1;i<=1000;i++)
        d[i]=i<x?inf:(x-i)*(x-i);
    for(i=1;i<n;i++){
        scanf("%d",&x);
        t=inf;
        for(j=1000;j>=1;j--)
            low[j]=t=min(t,d[j]+j*m);
        t=inf;
        for(j=1;j<=1000;j++){
            high[j]=t=min(t,d[j]-j*m);
            d[j]=inf;
        }
        for(j=x;j<=1000;j++)
            d[j]=(j-x)*(j-x)+min(low[j]-j*m,high[j]+j*m);
    }
    ans=inf;
    for(i=1;i<=1000;i++)
        ans=min(ans,d[i]);
    printf("%d\n",ans);
    return 0;
}
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yalishiyanzhouyu888/article/details/52556001
文章标签: poj dp
个人分类: poj dp
上一篇openjudge 海贼王之伟大航路(luoge.cpp/1000ms/128M)
下一篇最大公约数gcd.cpp
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭