首页 > 题解 > luogu 2885 [USACO07NOV]电话线Telephone Wire

luogu 2885 [USACO07NOV]电话线Telephone Wire

一道诡异的DP

地址 luogu2285

题目描述

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.

给出若干棵树的高度,你可以进行一种操作:把某棵树增高h,花费为h*h。

操作完成后连线,两棵树间花费为高度差*定值c。

求两种花费加和最小值。

输入输出格式

输入格式:

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.

输入输出样例

输入样例#1:

5 2
2
3
5
1
4

输出样例#1:

15

题解

裸的DP是非常好想的,$f[i][j]=min{f[i-1][k]+(j-h[i])^2+c*(k-j)}$

这样的话复杂度就是$O(n \times 100 \times 100)$

我们考虑怎么优化一下它

稍微观察一下,发现后面那一项是有单调性的,我们就可以枚举一下i和j,对于每一个状态,要不就是从上(下)面连过来,或者是从上一个j的高度连下来。而且只要有一个状态是从上一个j连过来,下面最优的上界就是这个柱子,就可以用单调队列优化下。

最后变成了 $ O(n \times 100) $。。。

#include 
#include 
#define inf 0x3f3f3f3f
using namespace std;
int f[100010][110];
int maxs,h[100010],n,c;
int min(int a,int b){return a=h[i];j--)
        {
            temp=min(temp+c,f[i-1][j]);
            f[i][j]=temp+(j-h[i])*(j-h[i]);
        }
        temp=inf;
        for (int j=1;j<=100;j++)
        {
            temp=min(temp+c,f[i-1][j]);
            f[i][j]=min(f[i][j],temp+(j-h[i])*(j-h[i]));
            if (j