DTOJ #5274. 割葱

题目

假设葱一共有 n n n 棵,第 i i i 棵葱的高度为 a [ i ] a[i] a[i]

Alice 一共要割最多 k k k 刀葱,每刀可以在某一高度割去连续一段葱。

以高度 h h h 在区间 [ l , r ] [l, r ] [l,r] 割一刀葱是合法的,当且仅当区间里的葱的高度都不小于 h h h,此时,这个区间中的葱小于等于 h h h 的未被割的部分都会被割掉。

下面的葱被割掉以后,上面的葱不会掉下来。

请问, k k k 刀以后,割掉的葱的总长度的最大值是多少?

数据范围

测试点 n n n k k k a [ i ] a[i] a[i]
1 − 4 1-4 14 ≤ 5 \le 5 5 ≤ 5 \le 5 5 ≤ 1 0 6 \le 10^6 106
5 − 8 5-8 58 ≤ 10 \le 10 10 ≤ 10 \le 10 10 ≤ 1 0 6 \le 10^6 106
9 − 10 9-10 910 ≤ 100 \le 100 100 ≤ 2 \le 2 2 ≤ 1 0 6 \le 10^6 106
11 − 12 11-12 1112 ≤ 100 \le 100 100 ≤ 100 \le 100 100 ≤ 100 \le 100 100
13 − 20 13-20 1320 ≤ 100 \le 100 100 ≤ 100 \le 100 100 ≤ 1 0 6 \le 10^6 106

对于所有数据, 1 ≤ n , k ≤ 100 , 1 ≤ a i ≤ 1 0 6 1 \le n,k \le 100,1 \le a_i \le 10^6 1n,k100,1ai106

题解

我们考虑到一段连续的区间,切掉最小值之后分为2个区间,这样到最后最多只有4n个区间。所以我们令 f [ i ] [ k ] [ l ] f[i][k][l] f[i][k][l] 表示第 i i i 个区间上一刀割在 l l l 高度,割了 k k k 刀之后的最大价值。于是我们就可以转移。令 x , y x,y x,y i i i 的子区间。
若当前这一刀不割区间最小值,则 f [ i ] [ k ] [ l ] f[i][k][l] f[i][k][l] 可以由 f [ x ] [ k 1 ] [ l ] , f [ y ] [ k − k 1 ] [ l ] f[x][k1][l],f[y][k-k1][l] f[x][k1][l],f[y][kk1][l]转移。
若割了最小值,令区间最小值为o,则由 f [ x ] [ k 1 ] [ o ] , f [ y ] [ k − k 1 − 1 ] [ o ] f[x][k1][o],f[y][k-k1-1][o] f[x][k1][o],f[y][kk11][o]转移。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=105;
int n,k,a[N],f[N*4][N][N],qu[N][N],tot,ans,hi[N*4];
void solve(int l,int r,int h){
	qu[l][r]=++tot;
	int p=0;
	for(int i=l;i<=r;++i)if(a[p]>a[i])p=i;
	hi[h]=a[p];
	if(p>l)solve(l,p-1,h+1);
	if(p<r)solve(p+1,r,h+1);
	int lt=qu[l][p-1],rt=qu[p+1][r];
	for(int i=0;i<=k;++i){
		for(int j=0;j<=h;++j){
			for(int ck=0;ck<=i;++ck)f[qu[l][r]][i][j]=max(f[qu[l][r]][i][j],f[lt][ck][j]+f[rt][i-ck][j]);
			for(int ck=0;ck<i;++ck)f[qu[l][r]][i][j]=max(f[qu[l][r]][i][j],f[lt][ck][h]+f[rt][i-ck-1][h]+(r-l+1)*(hi[h]-hi[j]));
		}
	}
}
int main(){
//	freopen("test.in","r",stdin);
//	freopen("test.out","w",stdout);
	scanf("%d%d",&n,&k);a[0]=1e9;
	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
	solve(1,n,1);
	printf("%d\n",f[qu[1][n]][k][0]); 
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值