BZOJ1933: [Shoi2007]Bookcase 书柜的尺寸

传送门

很容易看出来这是一道DP题,那么怎么设置状态就成了这道题的关键。本题有点特殊的地方是有两个维度的状态,而每个维度又有三个部分的参数,如果全部设置出来的话肯定会MLE。首先对书的厚度状态简化。

书的厚度是求和的,这个显然不能作为状态的值,作为状态的参数是比较好的, 30*70=2100 2100^3是内存无法接受的,简化状态求出前i本书的前缀和sum[i],如果第一层的厚度是i,第二层的厚度是j,那么第三层的状态显然是sum[i]-j-k,bingo,内存的问题解决了。显然两个维度一个维度表状态另一个维度显然表示权值。但是问题是,书是三层的高度,不可能把每一层都暴力表示出来,所以巧妙的地方是把书的高度递减排序。然后这个问题就显然很好解决了。

 1 //BZOJ 1933
 2 //by Cydiater
 3 //2016.8.26
 4 #include <iostream>
 5 #include <cstring>
 6 #include <string>
 7 #include <algorithm>
 8 #include <queue>
 9 #include <map>
10 #include <ctime>
11 #include <iomanip>
12 #include <cmath>
13 #include <cstdlib>
14 #include <cstdio>
15 using namespace std;
16 #define ll int
17 #define up(i,j,n)       for(ll i=j;i<=n;i++)
18 #define down(i,j,n)     for(ll i=j;i>=n;i--)
19 const int MAXN=2505;
20 const int oo=0x3f3f3f3f;
21 inline int read(){
22       char ch=getchar();int x=0,f=1;
23       while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
24       while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
25       return x*f;
26 }
27 ll N,f[2][2105][2105],sta=0,lim=0,sum[75],ans=oo;
28 struct _data{
29       ll h,t;
30 }a[75];
31 namespace solution{
32       inline bool cmp(_data x,_data y){return x.h>y.h;}
33       void init(){
34             N=read();
35             memset(sum,0,sizeof(sum));
36             up(i,1,N){
37                   a[i].h=read();a[i].t=read();
38                   lim+=a[i].t;
39             }
40             sort(a+1,a+N+1,cmp);
41             up(i,1,N)sum[i]=sum[i-1]+a[i].t;
42       }
43       void dp(){
44             memset(f,10,sizeof(f));
45             f[sta][0][0]=0;
46             up(i,1,N){
47                   sta^=1;memset(f[sta],10,sizeof(f[sta]));
48                   ll h=a[i].h,t=a[i].t;
49                   down(j,sum[i-1],0)down(k,sum[i-1],0){
50                         if(j+k>sum[i-1])continue;
51                         if(f[sta^1][j][k]>1000000)continue;
52                         if(j==0)                f[sta][t][k]=min(f[sta][t][k],f[sta^1][j][k]+h);
53                         else                    f[sta][j+t][k]=min(f[sta][j+t][k],f[sta^1][j][k]);
54                         if(k==0)                f[sta][j][t]=min(f[sta][j][t],f[sta^1][j][k]+h);
55                         else                    f[sta][j][k+t]=min(f[sta][j][k+t],f[sta^1][j][k]);
56                         if(sum[i-1]-j-k==0)     f[sta][j][k]=min(f[sta][j][k],f[sta^1][j][k]+h);
57                         else                    f[sta][j][k]=min(f[sta][j][k],f[sta^1][j][k]);
58                   }
59             }
60       }
61       void output(){
62             up(i,1,lim)up(j,1,lim)if(sum[N]-i-j>0&&f[sta][i][j]<10000){
63                   ans=min(ans,max(max(i,j),sum[N]-i-j)*f[sta][i][j]);
64             }
65             cout<<ans<<endl;
66       }
67 }
68 int main(){
69       //freopen("input.in","r",stdin);
70       using namespace solution;
71       init();
72       dp();
73       output();
74       return 0;
75 }

时间: 2024-10-21 22:53:12

BZOJ1933: [Shoi2007]Bookcase 书柜的尺寸的相关文章

[Shoi2007]Bookcase 书柜的尺寸 dp

这道dp算是同类型dp中比较难的了,主要难点在于设置状态上: 如果像平时那样设置,必定爆空间没商量: 下面是一种思路: 先把输入进来的数据按h从大到小排序,这样就可以大大减少状态数, 然后设f[i][j][k]为前i本书第一个书柜厚度j,第二个书柜厚度k,第三个书柜厚度sum[i]-j-k的h最大值得最小和: 这样一是将h放在了里面,相当于一个方程思想,因为s可以由h,t算出来: 二是转移的时候,如果j,k或sum[i]-j-k为0,直接加上h,因为前面的h比后面的大,方便了转移: 但我最后也是

BZOJ 1933 [Shoi2007]Bookcase 书柜的尺寸 ——动态规划

状态设计的方法很巧妙,六个值 h1,h2,h3,t1,t2,t3,我们发现t1,t2,t3可以通过前缀和优化掉一维. 然后考虑把h留下还是t留下,如果留下h显然t是会发生改变的,一个int存不下. 如果按照h降序排序,然后计算的时候存总的高度值,就很方便转移了. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std;

BZOJ 1933 [Shoi2007]Bookcase 书柜的尺寸

神奇的dp优化. 考虑6维状态的dp,分别表示三行高和宽,显然MLE&&TLE. 把高排个序,从大到小往架上放,那么若不是重开一行便对高度没有影响. 然后求出宽度的sum,dp[i][j]表示第一行放了i的宽度,二行放了j的宽度,三行放了sum-i-j宽度的最小的高度值. 先把所有书放在第三行,然后从第二本开始转移,考虑往其他行移的情况. 避免MLE要滚动数组. 注意最后更新答案时保证i>0&&j>0&&sum-i-j>0且dp[i][j]

这36张图包含了高中英语所有生活用词,果断收藏!

https://www.ddvip.com/weixin/20171130A01YV500.html 内容概要: 1. 1.buoyancy compensation device(BCD) 浮力补偿背心. 2. 12.tire 轮胎. 3. 1.lighter 打火机. 记住这些生活用语英语单词,不仅可以在亲戚朋友面前show off一番,而且可以扩充词汇量,提高英语水平和成绩,一举三得,何乐而不为呢? 1.教室 1.public-address speaker 广播 2.map 地图 3.c

English trip V1 - B 14. There Are Flowers in My Office 我办公室里有花 Teacher:Lamb Key: There be(is/are)

In this lesson you will learn to describe a room or place. 这节课讲学习描述一个房间或地方 课上内容(Lesson) 1. Where do you study or work? 你在哪学习/工作? Do you work at a desk?  你在办公桌前工作吗? Do you study at school?  你在学校学习吗? Do you work in your own office?  你在你自己的办公室工作吗? 2. Ta

dp优化总结

dp优化总结 一.滚动数组 典型的空间优化. 这应该是最最普通的一个优化了吧.. 对于某些状态转移第i个只需要用到第i-1个状态时,就可以用滚动数组,把第一维用0/1表示. 拓展1: 当一个状态转移要用到前m个转移时,我们依然可以滚起来,把第一维按模m的值滚起来. 拓展2: 若每一个决策可以选任意次(在一定限度下),那么我们可以借鉴完全背包的思路,把决策一个一个累计起来,起到优化时间的作用.(例题:NOIP2013 飞扬的小鸟) 二.数据结构优化 1.单调队列 如果一个转移方程模型大致如下: \

IOS中获取屏幕尺寸

//app尺寸,去掉状态栏 CGRect appRect = [UIScreen mainScreen].applicationFrame; NSLog(@"%f, %f, %f,%f",appRect.origin.x, appRect.origin.y, appRect.size.width,appRect.size.height); //屏幕尺寸 CGRect screenRect = [UIScreen mainScreen].bounds; NSLog(@"%f,

[[UIScreen mainScreen] bounds]获取尺寸不对

我在使用Xcode6时手动创建ViewController时也遇到了这样的问题,后来发现是因为项目设置中的Launch Images Source没有设置好的原因.因为把Xcode6自动生成的LaunchScreenController.xib删除了, 项目设置中的LaunchImages Source选项变成了 Use Asset Catalog,这时又没有指定正确的Images所以尺寸就不对了.解决办法是在Images.xcassets中创建LaunchImage,并将它做为Launch I

JS获取浏览器可视区域的尺寸

所谓可视区域是指能看得见的区域,即在浏览器中能看到页面的区域(高度与宽度).刚刚使用 document.body.clientHeight 来获取可视区域的高度得到的却是整个文档的高度,然后在cnblogs.com的一篇文章中获知需要通过 document.documentElement.clientHeight 才能获取到浏览器的可视区域的高度,顺便将该文章摘下来,如下: 在没有声明DOCTYPE的IE中,浏览器显示窗口大小只能以下获取: 1 2 document.body.offsetWid