码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj1233 干草堆 - 单调队列优化dp

时间:2018-08-12 23:42:54      阅读:425      评论:0      收藏:0      [点我收藏+]

标签:src   决策   .net   ide   问题   str   接下来   alt   class   

问题描述:

  若有干个干草, 分别有各自的宽度, 要求将它们按顺序摆放, 并且每层的宽度不大于 它的下面一层 ,  求最多叠几层

题解:    

    zkw神牛证明了: 底边最短, 层数最高         证明: 传送门

 

    接下来我们就可以根据这个结论进行dp。 前缀和sum, 以及 F[ i ]第 i 个数之后的干草叠起来后, 底层的最短宽度, 以及 H[ i ] 表示 第i个后的干草堆最高叠几层

    有转移方程 : F[ i ] = min( sum[ j - 1] - sum[i - 1] ) ( j > i && sum[ j - 1] - sum[ i - 1] >= f[ j ] )  由于前缀和从前往后是递增的, 所以 j 越小越好。

    又因为要满足 sum[ j - 1] - f[ j ] >= sum[ i - 1 ] , 所以 sum[ j - 1] - f[ j ] 越大越好, 可以用单调队列来使决策具有单调性, 每次取出队首就是最优决策

    

代码

  

技术分享图片
 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define rd read()
 5 #define rep(i,a,b) for( int i = (a); i <= (b); ++i )
 6 #define per(i,a,b) for( int i = (a); i >= (b); --i )
 7 using namespace std;
 8 
 9 const int N = 1e5 + 1e4;
10 
11 int n, a[N], sum[N], f[N], h[N], q[N];
12 
13 int read() {
14     int X = 0, p = 1; char c = getchar();
15     for(; c > 9 || c < 0; c = getchar() ) if( c == - ) p = -1;
16     for(; c >= 0 && c <= 9; c = getchar() ) X = X * 10 + c - 0;
17     return X * p;
18 }
19 
20 int main()
21 {
22     n = rd;
23     rep( i, 1, n ) sum[i] = sum[i - 1] + rd;
24     int l = 1, r = 1;
25     q[r] = n + 1;
26     sum[n + 1] = sum[n];
27     per( i, n, 1 ) {
28         while( l < r && f[ q[l + 1] ] <= sum[ q[l + 1] - 1] - sum[i - 1] ) l++;
29         f[i] = sum[ q[l] - 1] - sum[i - 1];
30         h[i] = h[q[l]] + 1;
31         while( l < r && sum[q[r] - 1] - f[q[r]] <= sum[i - 1] - f[i] ) r--;
32         q[++r] = i;
33     }
34     printf("%d\n",h[1]);
35 }
View Code

 

bzoj1233 干草堆 - 单调队列优化dp

标签:src   决策   .net   ide   问题   str   接下来   alt   class   

原文地址:https://www.cnblogs.com/cychester/p/9465332.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!