codeforces 1012C
题意:
给
定
n
座
山
的
高
度
,
第
i
座
山
的
高
度
为
a
i
。
给定n座山的高度,第i座山的高度为a_i。
给定n座山的高度,第i座山的高度为ai。
你
需
要
在
n
座
山
上
一
共
造
[
n
2
]
座
房
子
,
且
房
子
只
能
造
在
高
于
两
边
山
的
山
坡
上
。
你需要在n座山上一共造[\frac n2]座房子,且房子只能造在高于两边山的山坡上。
你需要在n座山上一共造[2n]座房子,且房子只能造在高于两边山的山坡上。
你
可
以
在
一
小
时
内
减
少
任
意
山
的
高
度
。
你可以在一小时内减少任意山的高度。
你可以在一小时内减少任意山的高度。
问
修
建
k
(
1
≤
k
≤
[
n
2
]
)
座
房
子
的
最
短
用
时
,
要
求
输
出
所
有
情
况
。
问修建k(1≤k≤[\frac n2])座房子的最短用时,要求输出所有情况。
问修建k(1≤k≤[2n])座房子的最短用时,要求输出所有情况。
题解:
d p [ i ] [ j ] [ k ] 表 示 在 区 间 [ 1 , i ] 内 建 j 座 房 子 , 且 在 第 i 座 山 建 ( k = 1 ) 或 不 建 ( k = 0 ) 房 子 的 最 短 用 时 。 dp[i][j][k]表示在区间[1,i]内建j座房子,且在第i座山建(k=1)或不建(k=0)房子的最短用时。 dp[i][j][k]表示在区间[1,i]内建j座房子,且在第i座山建(k=1)或不建(k=0)房子的最短用时。
- 第 i 座 山 不 建 房 子 , d p [ i ] [ j ] [ 0 ] = m i n ( d p [ i − 1 ] [ j ] [ 0 ] , d p [ i − 1 ] [ j ] [ 1 ] + m a x ( 0 , a [ i ] − a [ i − 1 ] + 1 ) ) 第i座山不建房子,dp[i][j][0] = min(dp[i-1][j][0], dp[i-1][j][1]+max(0, a[i]-a[i-1]+1)) 第i座山不建房子,dp[i][j][0]=min(dp[i−1][j][0],dp[i−1][j][1]+max(0,a[i]−a[i−1]+1))
- 第 i 座 山 建 房 子 , d p [ i ] [ j ] [ 1 ] = m i n ( d p [ i − 2 ] [ j − 1 ] [ 0 ] + m a x ( 0 , a [ i − 1 ] − a [ i ] + 1 ) , d p [ i − 2 ] [ j − 1 ] [ 1 ] + m a x ( 0 , a [ i − 1 ] − m i n ( a [ i − 2 ] , a [ i ] ) + 1 ) ) 第i座山建房子,dp[i][j][1] = min(dp[i-2][j-1][0]+max(0, a[i-1]-a[i]+1), dp[i-2][j-1][1]+max(0, a[i-1]-min(a[i-2], a[i])+1)) 第i座山建房子,dp[i][j][1]=min(dp[i−2][j−1][0]+max(0,a[i−1]−a[i]+1),dp[i−2][j−1][1]+max(0,a[i−1]−min(a[i−2],a[i])+1))
#include <bits\stdc++.h>
using namespace std;
const int N = 5005;
int a[N];
int dp[N][N/2][2];
int main() {
int n;
cin >> n;
for(int i = 1 ; i <= n ; i++){
cin >> a[i];
}
memset(dp, 0x3f, sizeof(dp));
dp[1][0][0] = dp[1][1][1] = 0;
for(int i = 2 ; i <= n ; i++){
dp[i][0][0] = 0;
for(int j = 1 ; j <= (i+1)/2 ; j++){
dp[i][j][0] = min(dp[i-1][j][0], dp[i-1][j][1]+max(0, a[i]-a[i-1]+1));
dp[i][j][1] = min(dp[i-2][j-1][0]+max(0, a[i-1]-a[i]+1), dp[i-2][j-1][1]+max(0, a[i-1]-min(a[i-2], a[i])+1));
}
}
for(int i = 1 ; i <= (n+1)/2 ; i++){
cout << min(dp[n][i][0], dp[n][i][1]) << ' ';
}
return 0;
}