韩父有N个儿子,分别是韩一,韩二…韩N。由于韩家演技功底深厚,加上他们间的密切配合,演出获得了巨大成功,票房甚至高达2000万。舟子是名很有威望的公知,可是他表面上两袖清风实则内心阴暗,看到韩家红红火火,嫉妒心遂起,便发微薄调侃韩二们站成一列时身高参差不齐。由于舟子的影响力,随口一句便会造成韩家的巨大损失,具体亏损是这样计算的,韩一,韩二…韩N站成一排,损失即为C*(韩i与韩i+1的高度差(1<=i<N))之和,搞不好连女儿都赔了.韩父苦苦思索,决定给韩子们内增高(注意韩子们变矮是不科学的只能增高或什么也不做),增高1cm是很容易的,可是增高10cm花费就很大了,对任意韩i,增高Hcm的花费是H^2.请你帮助韩父让韩家损失最小。
Input
有若干组数据,一直处理到文件结束。 每组数据第一行为两个整数:韩子数量N(1<=N<=50000)和舟子系数C(1<=C<=100) 接下来N行分别是韩i的高度(1<=hi<=100)。
首先建立方程,很容易想到的是,dp[i][j]表示第 i 个儿子身高为 j 的最低花费。分析题目很容易知道,当前儿子的身高花费只由前一个儿子影响。因此,
dp[i][j]=min(dp[i-1][k] + abs(j-k)*C + (x[i]-j)*(x[i]-j));其中x[i]是第i个儿子原本的身高
我们分析一下复杂度。
首先有N个儿子,这需要一个循环。再者,每个儿子有0到100的身高,这也需要一维。再再者,0到100的每一个身高都可以有前一位儿子的身高0到100递推而来。
所以朴素算法的时间复杂度是O(n^3)。题目只给两秒,难以接受!
分析方程:
当第 i 个儿子的身高比第 i-1 个儿子的身高要高时,
dp[i][j]=min(dp[i-1][k] + j*C-k*C + X); ( k<=j ) 其中 X=(x[i]-j)*(x[i]-j)。
当第 i 个儿子的身高比第 i-1 个儿子的身高要矮时,
dp[i][j]=min(dp[i-1][k] - j*C+k*C + X); ( k>=j )
对第一个个方程,我们令 f[i-1][k]=dp[i-1][k]-k*C, g[i][j]=j*C+X; 于是 dp[i][j] = min (f[i-1][k])+ g[i][j]。转化成这样的形式,我们就可以用单调队列进行优化了。
第二个方程同理。
接下来便是如何实现,实现起来有点技巧。
很容易想到在枚举每个儿子的时候,当前儿子的花费都会受到且只受到前一个儿子的影响,可以建一个dp[i][j]表示当前第i个孩子身高为j的情况。状态转移方程为dp[i][j]=min(dp[i-1][k] + abs(j-k)C + (a[i]-j)(a[i]-j)) a[i]是当前枚举人本身的身高,我们知道他们都可以增高,所以你在状态转移的时候,需要枚举前一个人的身高和这个人的身高k和j,a[k]<=k<=100,a[j]<=j<=100(注意只能增高——可能穿了什么恨天高牌增高鞋),这样dp确实可以d,但是不要高兴的太早了——我们来分析一下时间复杂度——我们要枚举每个人,枚举到每个人的时候还要枚举当前人的身高,还有之前人的身高,从给出的Input数据来看,在两秒的时间限制内————超时!怎么办,玫瑰色的人生还没有开始就结束了,我能怎么办,我也很绝望…
不过不用着急,我们可以用单调队列来帮你解决.分析一下这个方程,我们可以看到有一个abs的东西,即是绝对值,所以我们来分析两种情况,一种是前面那个人比当前枚举的人高,一种前面那个人比当前枚举的人矮,这样我们就可以吧绝对值的帽子去掉,建设新农村…好吧优化dp的新办法。我们看一下去掉绝对值的方程.
当第 i 个儿子的身高比第 i-1 个儿子的身高要高时,
dp[i][j]=min(dp[i-1][k] + j*C-k*C + X); ( k<=j ) 其中 X=(x[i]-j)*(x[i]-j)。
当第 i 个儿子的身高比第 i-1 个儿子的身高要矮时,
dp[i][j]=min(dp[i-1][k] - j*C+k*C + X); ( k>=j ).
我们便可以在去掉绝对值的情况下进行分类讨论.首先,我们先令一个二维数组f,f[i-1][k]=dp[i-1][k]-k*C, g[i][j]=j*C+X; 于是dp[i][j] =min (f[i-1][k])+g[i][j]。
在两个取绝对值的式子里面,我们可以看到都需要前一个人的花费求到一个最小值来更新当前状态,那我们可以建造一个单调递增的队列,在枚举第i个人的时候,我们把前一个人(i-1)在不同身高的状态所用的花费做成一个这样的单调队列,这样就不用枚举前一个人的身高(因为我们想要的最小值已经求出来了),所以就大大减少了时间复杂度