Hills——一道转移方程很“有趣”的线性DP
题目描述
Welcome to Innopolis city. Throughout the whole year, Innopolis citizens suffer from everlasting city construction.
From the window in your room, you see the sequence of n hills, where i-th of them has height ai. The Innopolis administration wants to build some houses on the hills. However, for the sake of city appearance, a house can be only built on the hill, which is strictly higher than neighbouring hills (if they are present). For example, if the sequence of heights is 5, 4, 6, 2, then houses could be built on hills with heights 5 and 6 only.
The Innopolis administration has an excavator, that can decrease the height of an arbitrary hill by one in one hour. The excavator can only work on one hill at a time. It is allowed to decrease hills up to zero height, or even to negative values. Increasing height of any hill is impossible. The city administration wants to build k houses, so there must be at least k hills that satisfy the condition above. What is the minimum time required to adjust the hills to achieve the administration's plan?
However, the exact value of k is not yet determined, so could you please calculate answers for all k in range ? Here denotes n divided by two, rounded up.
Input
The first line of input contains the only integer n (1 ≤ n ≤ 5000)—the number of the hills in the sequence.
Second line contains n integers ai (1 ≤ ai ≤ 100 000)—the heights of the hills in the sequence.
Output
Print exactly numbers separated by spaces. The i-th printed number should be equal to the minimum number of hours required to level hills so it becomes possible to build i houses.
Examples
5
1 1 1 1 1
1 2 2
3
1 2 3
0 2
5
1 2 3 2 2
0 1 3
Note
In the first example, to get at least one hill suitable for construction, one can decrease the second hill by one in one hour, then the sequence of heights becomes 1, 0, 1, 1, 1 and the first hill becomes suitable for construction.
In the first example, to get at least two or at least three suitable hills, one can decrease the second and the fourth hills, then the sequence of heights becomes 1, 0, 1, 0, 1, and hills 1, 3, 5 become suitable for construction.
题目大意:
有n座山,在山上建房子,需要保证有房子的山的高度比它两边的山的高度都要高,否则,就把比它高的山挖到比它低。每分钟可以令一座山的高度减一,分别求建1~n/2幢房子花费的最短时间
思路分析:
又是一个线性DP,一步一步往后推就行了
题目不是很难理解,但是最后让求的这个东西就比较有意思了,1~n/2,为什么是n/2而不是n?——显然,两座相邻的山没法同时建房子,要不你就挖去吧,地心挖穿也建不成(开个玩笑)。注意:这里得到一个很关键的性质——所建的房子必须相间,相间,相间!!!
常规思路,从1到n,当做终点进行处理,那我们就只需考虑这个终点前面的山的高度,但是这道题不一样在哪里了呢?——每个点有两点状态,即建房子或不建房子,那么怎么处理呢?数组多开一维不就得了,b( ̄▽ ̄)d
每个点的两种状态各需要一个转移方程,一个建房子的,一个不建房子的。
(1)第i座山建房子的:(划重点)第i座山如果建房子的话,那么第i-1座山肯定不能建,经过这座山时也不会增加时间,那我们就直接蹦到i-2去考虑。i-2同样也有两种情况,建或不建——如果不建,那就拿第i座和第i-1座比较,看看要不要挖;如果建了,那就拿i-2和n共同与i-1进行比较,因为i-1要满足比它们两个都要低。
(2)第i座山不建房子的:那这个时候i-1就可以考虑建房子了,这个情况就比较简单了
细节见代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int maxn = 5000+10; int h[maxn]; int dp[maxn][maxn][2]; int main(){ memset(dp,0x3f,sizeof(dp)); dp[0][0][0]= dp[1][1][1] = dp[1][0][0] =0; //初始化,这里其实省了一个循环,把dp[i][0][0]放到下面的dp循环里了 h[0]=0x3f3f3f3f; //设为无限大,是为了不干扰后面的操作,而且h[0]一定会出现 int n;scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d",&h[i]); } for(int i=2;i<=n;++i){ dp[i][0][0]=dp[i-1][0][0]; //前面省的初始化化放到这里了 for(int j=1;j<=(i+1)/2;++j){ //这个括号可能有点长,但其实并不太复杂 dp[i][j][1]=min(dp[i-2][j-1][0]+max(0,h[i-1]-h[i]+1), //max函数,其实是代替了if,如果h[i-1]-h[i]+1小于0,说明i-1更矮,就不用挖掉了 dp[i-2][j-1][1]+max(0,h[i-1]-min(h[i],h[i-2])+1)); //h[i]和-2],哪个高出来得更多,就挖哪个,这样另一个就也比i-1矮了 dp[i][j][0]=min(dp[i-1][j][0], dp[i-1][j][1]+max(0,h[i]-h[i-1]+1)); //上面那个理解了这个就没问题了 } } for(int i=1;i<=(n+1)/2;++i){ printf("%d ", min(dp[n][i][0],dp[n][i][1])); } return 0; }
写了这么多,你会明白的对吧(*╹▽╹*)