CodeForces1400E 分治
题意
蕊蕊最近在玩一个消消乐游戏,这个消消乐的规则和一般的消消乐不同,玩法很简单只有两种操作:
选取一个相连的块,将这个块的最底部一行方块消去,上面的部分随之落下
选取一列,直接消去
如果一个区间内每一列的方块数打都大于0,则称这个区间是一个相连的块,显然任何相连的块的子区间也是一个相连的块
现在告诉你每一列的高度,你要帮助蕊蕊在最少的操作内将所有方块消去
解法
将连通的一段序列称为一个“元”,一个元可以通过两种方式消除掉
- 进行n次操作2,暴力删除
- 进行min{a[l] ~ a[r]} 次的操作1,消除最低高度的块,将一个元划分为多个元
划分出来的元可以递归解决
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5010;
int N;
const int INF = 0x3f3f3f3f;
int a[maxn];
int solve(int l, int r, int h, bool flag) {
if(l > r) {
return 0;
}
int m = INF;
for(int i = l; i <= r; i ++) m = min(m, a[i]);
m -= h;
if(!m && !flag) return 0;
int ans = m;
int la = l;
for(int i = l ; i <= r; i ++) {
if(a[i] - h - m == 0) {
ans += solve(la, i - 1, h + m, false);
la = i + 1;
}
}
ans += solve(la, r, h + m,false);
return min(r - l + 1, ans);
}
int main() {
scanf("%d", &N);
for(int i = 1; i <= N ; i ++) {
scanf("%d",&a[i]);
}
printf("%d\n",solve(1,N,0,true));
return 0;
}