【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); }