[bzoj1233]干草堆tower

[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;
}

猜你喜欢

转载自blog.csdn.net/qq_35923186/article/details/83241905