译文及题解 电话线Telephone Wire(动态规划)

来源:互联网 发布:tcp通信安卓app源码 编辑:程序博客网 时间:2024/05/16 01:10

电话线Telephone Wire
[USACO07NOV]

Question In English(BY USACO)
中文翻译(翻译自Stockholm_Sun)

Telephone Wire
电话线

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.
农夫约翰的牛们对他们烂到爆的电话服务感到焦躁不安;他们想让农夫约翰把旧的电线换成全新的并且更高效的电线。这组新的线路将会利用N(2 ≤ N ≤ 100,000) 条已经安装了的电线杆,每个电话杆都有H(i)米高(1 ≤ H(i) ≤ 100)。这个新的电话线将会连接每一对相邻的电线杆,并且会产生(C*两电线杆高度之差)的代价(1 ≤ C ≤ 100)。当然,电线杆是有序的而且不能被移走。

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.
农夫约翰想到了这样一个事实:如果他让一些电线杆变得更高,那么他就可以减少他的花费,尽管还有一些额外的花费。它能够花X^2的代价给一个电线杆增加X的高度(附注:可以给任意电线杆增加任意正整数高度)。

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 & Output Format
输入输出格式

Input Format
Line 1: Two space-separated integers: N and C
Lines 2..N+1: Line i+1 contains a single integer: heighti
输入格式:
第1行:两个用空格分开的整数:N和C
第2至N+1行:第i+1包含一个单独的整数:H(i)

Output Format
Line 1: The minimum total amount of money that it will cost Farmer John to attach the new telephone wire.
输出格式:
第1行:农夫约翰连接新电话线所花费的最少总钱数。

Samples Input & Samples Output
输入输出样例

Samples Input
输入样例#
5 2
2
3
5
1
4

Samples Output
输出样例#1:
15

思路

看到题目,我们考虑动态规划,先假设f[ x ]为在x之前花费的最小价格,但是我们需要考虑为电线杆增加高度。
所以考虑升维,既然高度未知,我就升维,f[ x ][ h ]就是前x个电线杆,且第x个高度为h的最小花费。
我们就可以枚举前一个的高度和当前杆子的高度,从前一个转移而来:f[i][j]=min{f[i-1][k]+(j-h[i])*(j-h[i])+abs(j-k)*p};这个就是状态转移方程。
最后答案为f[n][i]max。

代码

#include<iostream>#include<cmath>#include<cstdio>#include<cstdlib>#include<cstring>#include<deque>#include<algorithm>using namespace std;  long long i,j;long long k,n,p;long long h[100001],f[100001][101];long long r(){    long long p=0,f=1;    char c=getchar();    while(c<'0'||c>'9')    {        if(c=='-')        {            f=-1;        }        c=getchar();    }    while(c>='0'&&c<='9')    {        p=p*10+c-'0';        c=getchar();    }    return p*f;}char chr;int main(){//  freopen("out.txt","w",stdout);    n=r(),p=r();    long long maxx=0;    for(i=1;i<=n;i++)    {        h[i]=r();        if(h[i]>maxx)        maxx=h[i];    }    memset(f,0x7f7f7f,sizeof(f));    for(i=h[1];i<=100;i++)    f[1][i]=(i-h[1])*(i-h[1]);    long long ans=0x7fffffff;    for(i=2;i<=n;i++)    for(j=h[i];j<=maxx;j++)    {        ans=0x7fffffff;        for(k=h[i-1];k<=maxx;k++)        {            if(f[i-1][k]+(j-h[i])*(j-h[i])+abs(j-k)*p<f[i][j])            f[i][j]=f[i-1][k]+(j-h[i])*(j-h[i])+abs(j-k)*p;            if(f[i][j]>ans) break;            else ans=f[i][j];        }    }    ans=0x7fffffff;    for(i=h[n];i<=100;i++)    ans=min(ans,f[n][i]);    cout<<ans;    return 0;}/**/

这里写图片描述

原创粉丝点击