BZOJ1233【usaco open 2009】干草堆 tower

【BZOJ1233】【usaco open 2009】干草堆 tower

【问题描述】

Bessie必须建一座干草堆。一共有N大包的干草(1<=N<=100000)(从1到N编号)依靠传送带连续的传输进牛棚来。第i包干草有一个 宽度W_i(1<=w_i<=10000),高度为1。 Bessie必须利用所有N包干草来建立起干草堆,按顺序严格摆放。说得更清楚一些:一旦她将一个草包放在第二级 ,她不能将接下来的草包放在地基上。要求每一级不能比下面的一级宽。求最大高度。

Input

第1行:一个单一的整数N。 第2~N+1行:一个单一的整数:W_i。

Output

第一行:一个单一的整数,表示Bessie可以建立的草包堆的最高高度。

Sample Input

3

1

2

3

Sample Output

2

输出说明:

前两个(宽度为1和2的)放在底层,总宽度为3,在第二层放置宽度为3的。

       +----------+

       |    3     |

       +---+------+

       | 1 |   2  |

       +---+------+

【分析】

这道题一眼看过去可能觉得可以贪心,但贪心是不行的,之后再说。

正解还是动规。

先要了解一个结论,在多种可行的堆叠方案中,至少有一种能使层数最高的方案同时使得底边最短。即底边最短的,层数一定最高。证明:(引用张昆玮大牛,虽然我不知道是谁)

 任意取出一个能使层数最高的方案,设有CA层,把其中从下往上每一层最大的块编号记为Ai;任取一个能使底边最短的方案,设有CB层,把其中从下往上每一层最大的块编号记为Bi。显然A1>=B1,ACB<=BCB,这说明至少存在一个k属于(1,CB),满足Ak-1>=Bk-1且Ak<=Bk。也就是说,方案 A 第K 层完全被方案 B 第K 层包含。构造一个新方案,第K 层往上按方案 A,往下按方案 B,两边都不要的块放中间当第K 层。新方案的层数与 A 相同,而底边长度与 B 相同。证毕。

 知道这个结论后,贪心就明显不可行了。比如a + b> c+ d,b + c < d,贪心的结果是a,b,c||d,而a,b||c,d则更优。

 设F[i]为第i..N个干草包所叠成的塔底层最短边的值,同时用g[i]记下此时的层数。

 F[i]=min(sum[j-1]-sum[i-1])  j>i 且 sum[j-1]-sum[i-1]>=F[j]

 像这样O(n^2)的算法明显过不了,要进行优化。

 我们发现在阶段i时,对于k>j>i,j会比k优,决策为k的情况只能是J不满足条件而k满足条件,整理方程得

      f[j] - sum[j - 1] > f[k]-sum[k - 1]

 所以我们可以用一个单调队列来维护。均摊时间为o(n).

【代码】

//bzoj1233 [Usaco2009Open]干草堆tower
#include
#include
#include
#include
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=100005;
int n,x;
int sum[mxn],f[mxn],g[mxn],q[mxn];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int main()
{
    int i,j;
    n=read();
    fo(i,1,n)
    {
        x=read();
        sum[i]=sum[i-1]+x;
    }
    int h=1,t=1;
    q[1]=n+1;
    for(i=n;i>=1;i--)
    {
        while(hq[h+1]-1]-sum[i-1]>=f[q[h+1]]) h++;//必须满足越到上层越短的条件
        f[i]=sum[q[h]-1]-sum[i-1];
        g[i]=g[q[h]]+1;
        while(hq[t]]-sum[q[t]-1]>f[i]-sum[i-1]) t--;
        q[++t]=i; 
    }
    printf("%d\n",g[1]);
    return 0;
}

你可能感兴趣的:(单调队列优化DP)