51nod 1519 拆方块
有n堆方块,第i堆方块由hi个方块堆积而成。具体可以看样例。
接下来拆方块。一个方块称为内部方块当且仅当他的上下左右都是方块或者是地面。否则方块就是边界方块。每一次操作都要把边界方块拿掉。
问多少次操作之后所有方块会消失。
样例解释:
每一次操作,边界方块被标记为红色。
经过第一次操作,只剩下四个方块。第二次操作之后,只剩下一个方块。
对于这个题目,我们把一个方块被拆下来的原因分成两种。
第一种:因为左边 或者 上边没有方块
第二种:因为右边 或者 上边没有方块
更一般的,我们从新定义外部方块。
第一种外部方块:左边或者上边没有方块的方块
第二种外部方块:右边或者上边没有方块的方块
那么,一列方块被消去的最少操作次数,等于:
以两种外部方块消去的次数最少的那一种
设 L[i],R[i] 分别表示,第i列,以第一种和第二种消去的最少次数,H[i]为第i列原始方块的数量。
当某一列的左侧没有方块时,则这一列最多再进行一次操作即:
L[i+1]−L[i]<=1
当某一列的右侧没有方块时,则这一列最多再进行一次操作即:
R[i]−R[i+1]<=1
当某一侧的操作次数超过了这一列的方块数量,则有:
L[i]=H[i]R[i]=H[i]
综上:
L[i]={H[i] , H[i]<=L[i−1]L[i−1]+1 , H[i]>L[i−1]
R[i]={H[i] , H[i]<=R[i+1]R[i+1]+1 , H[i]>R[i+1]
所以:
answer=MAXni=1(min(L[i],R[i]))
下面是AC代码
#include <stdio.h>
#include <algorithm>
using namespace std;
int L[100005],R[100005],H[100005];
int main ()
{
int n;
scanf("%d",&n);
n++;
for(int i=1;i<n;i++) scanf("%d",H+i);
for(int i=1;i<n;i++)
{
L[i]=L[i-1]+1;
if(L[i]>H[i]) L[i]=H[i];
}
for(int i=n-1;i;i--)
{
R[i]=R[i+1]+1;
if(R[i]>H[i]) R[i]=H[i];
}
int ans=0;
for(int i=1;i<n;i++)
ans=max(ans,min(L[i],R[i]));
printf("%d\n",ans);
return 0;
}