[bzoj1233]干草堆tower
首先,倒着直接贪心是会被卡的
数据如下:
6 11 10 7 3 2 6
然后我们可以发现一些性质:每个点取能取的最小的宽度,这样一定能构成最优解
然后状态是f[x]表示x位置的最小宽度
f[x]=min( s[y - 1] - s[x - 1] ) ( s[y - 1] - s[x - 1] >= f[y] )>>>>>>s[x - 1] <= s[y - 1] - f[y]
注意f不是单调的,数据如下:
5 3 2 4 1 4
但是我们可以用单调队列来优化dp
- 代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+1;
int n,w[N],s[N],ans[N],f[N];
typedef pair<int,int> pii;
#define x first
#define y second
pii Q[N];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&w[i]);s[i]=s[i-1]+w[i];
}
int l=1,r=1;
Q[1]=pii(n+1,s[n]);
for(int i=n;i;i--){
while(l<r&&Q[l+1].y>=s[i-1])l++;
f[i]=s[Q[l].x-1]-s[i-1];
//cout<<f[i]<<' ';
ans[i]=ans[Q[l].x]+1;
pii cur=pii(i,s[i-1]-f[i]);
while(l<=r&&Q[r].y<=cur.y)r--;
Q[++r]=cur;
}
printf("%d\n",ans[1]);
return 0;
}