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]!=INF;

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
typedef long long LL;
using namespace std;
int n,sum,f[2][2150][2150],ans=1e9;
struct book {
    int hi,ti;
    friend bool operator <(const book &A,const book &B) {
        return A.hi>B.hi;
    }
}bk[75];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&bk[i].hi,&bk[i].ti);
    sort(bk+1,bk+n+1);
    for(int i=1;i<=n;i++) sum+=bk[i].ti;
    int o=0;
    memset(f,127/3,sizeof(f));
    f[0][0][0]=bk[1].hi;
    for(int i=2;i<=n;i++) {
        o^=1;
        for(int j=0;j<=sum;j++) {
            for(int k=0;k<=sum&&j+k<sum;k++) {
                f[o][j][k]=min(f[o][j][k],f[o^1][j][k]);
                if(!j) f[o][j+bk[i].ti][k]=min(f[o][j+bk[i].ti][k],f[o^1][j][k]+bk[i].hi);
                else f[o][j+bk[i].ti][k]=min(f[o][j+bk[i].ti][k],f[o^1][j][k]);
                if(!k) f[o][j][k+bk[i].ti]=min(f[o][j][k+bk[i].ti],f[o^1][j][k]+bk[i].hi);
                else f[o][j][k+bk[i].ti]=min(f[o][j][k+bk[i].ti],f[o^1][j][k]);
                if(i==n&&j!=0&&k!=0&&f[o][j][k]!=707406378) {
                    ans=min(ans,f[o][j][k]*max(max(j,k),sum-j-k));
                }
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

时间: 2024-10-01 16:12:16

BZOJ 1933 [Shoi2007]Bookcase 书柜的尺寸的相关文章

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;

BZOJ1933: [Shoi2007]Bookcase 书柜的尺寸

传送门 很容易看出来这是一道DP题,那么怎么设置状态就成了这道题的关键.本题有点特殊的地方是有两个维度的状态,而每个维度又有三个部分的参数,如果全部设置出来的话肯定会MLE.首先对书的厚度状态简化. 书的厚度是求和的,这个显然不能作为状态的值,作为状态的参数是比较好的, 30*70=2100 2100^3是内存无法接受的,简化状态求出前i本书的前缀和sum[i],如果第一层的厚度是i,第二层的厚度是j,那么第三层的状态显然是sum[i]-j-k,bingo,内存的问题解决了.显然两个维度一个维度

[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 1934: [Shoi2007]Vote 善意的投票 最小割

1934: [Shoi2007]Vote 善意的投票 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1934 Description 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神.虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票.我们定义一次投票的冲突数

BZOJ 1934 [Shoi2007]Vote 善意的投票(最小割)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1934 [题目大意] 每个人对于投票都有自己原来的观点:1或者0, 他可以违背自己原来的意愿投相反的票, 同时存在一些相互的朋友关系, 我们定义一次投票的冲突数为好朋友之间发生冲突的总数, 加上和所有和自己本来意愿发生冲突的人数. 求最小冲突. [题解] 我们将好友之间连双向边,流量为1,对于原本意愿为1的连源点,0的连汇点,流量为1, 该图最小割即为最小冲突. [代码] #inclu

BZOJ 1935: [Shoi2007]Tree 园丁的烦恼 [树状数组 离线 离散化]

传送门 刚才我还在郁闷网上怎么没人用$CDQ$分治做 突然发现根本没有时间序.... #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=3e6+5; inline int read(){ char c=getchar();int x=0,f=1; whi

BZOJ 1934 [Shoi2007]Vote 善意的投票

我大概是把自己水废掉了. 第一眼匈牙利?不知道怎么想到的,然后发现不可做. 似乎是网络流呀. 看了半天硬是没把图建出来. 出去冷静一下. wc这不是和文理分科那啥一模一样嘛,还简单得多... 我是zz,鉴定完毕. //Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring

BZOJ 1935 SHOI2007 园丁的烦恼 树状数组

题目大意:给定平面上的一些点,多次询问某个矩形中有多少个点 将每个询问拆成4个 然后把所有询问和点都按照横坐标排序 对于每个询问,将所有x值小于等于这个询问的x的点的y值加入树状数组 然后在树状数组上查询小于等于这个询问的y值的点的数量 别被1000W吓到了 如果不爆内存的话1E也是能搞的 套个log就没多少了 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm&

BZOJ.1935.[SHOI2007]Tree园丁的烦恼(CDQ分治 三维偏序)

题目链接 矩形查询可以拆成四个点的前缀和查询(树套树显然 但是空间不够) 每个操作表示为(t,x,y),t默认有序,对x分治,y用树状数组维护 初始赋值需要靠修改操作实现. //119964kb 4380ms #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar() #define lb(x) (x)&-(x) const int N=5e5+5; int n,