【51nod1519】拆方块[Codeforces](dp)

  题目传送门:1519 拆方块

  首先,我们可以发现,如果第i堆方块被消除,只有三种情况:

  1、第i-1堆方块全部被消除;

  2、第i+1堆方块全部被消除;(因为两侧的方块能够保护这一堆方块在两侧不暴露)

  3、第i堆方块过了h[i]次操作后,从上到下被消除。

  于是我们设l[i]为第i堆方块从左边开始消除的最小操作次数,设r[i]从右边开始消除的最小操作次数。

  然后从左向右dp出l[i],从右向左dp出r[i],然后就能算答案了。

  代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<queue>
#include<vector>
#define ll long long
ll read()
{
    ll tmp=0; char f=1,c=getchar();
    while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
    while('0'<=c&&c<='9'){tmp=tmp*10+c-'0';c=getchar();}
    return tmp*f;
}
using namespace std;
int l[100010],r[100010],h[100010];
int main()
{
    int n=read(),i;
    for(i=1;i<=n;i++)h[i]=read();
    l[1]=1; for(i=2;i<=n;i++)l[i]=min(l[i-1]+1,h[i]);
    r[n]=1; for(i=n-1;i;i--)r[i]=min(r[i+1]+1,h[i]);
    int ans=min(l[1],r[1]);
    for(i=2;i<=n;i++)ans=max(ans,min(l[i],r[i]));
    printf("%d",ans);
}
View Code
原文地址:https://www.cnblogs.com/quzhizhou/p/7449344.html