ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【SHOI2007】书柜的尺寸

2019-08-26 22:06:19  阅读:205  来源: 互联网

标签:h2 高度 t2 t3 t1 书柜 尺寸 SHOI2007 dp


dp

如果我们直接定义状态:

\(dp[i][t1][t2][t3][h1][h2][h3]\)表示前i个,第一层宽度为t1,,第二层宽度为t2,第三层宽度为t3,第一层高度为h1,第二层高度为h2,第三层高度为h3的最小面积。

如果直接这样定义,你会发现,你不仅内存炸飞,时间也会T的飞起。

考虑优化状态。

1.首先,你会发现,面积可以直接用t1,t2,t3,h1,h2,h3算出来,所以我们不妨砍掉一维

2.列一波状态转移方程,你会发现,i只会从i-1转移过来,于是又可以把第一维滚动

3.不难发现,\(t1+t2+t3=\sum _{j=1}^{j \le i} t_j\)于是只用知道t1,t2,t3中的任意两个,就可以推出第三个

那么,状态就优化成了:\(dp[0/1][t1][t2][h1][h2]\)表示前i个,第一层宽度为t1,,第二层宽度为t2,第一层高度为h1,第二层高度为h2,的第三层最小高度。

然后,你又会发现,内存和时间依旧承受不住。。。

仔细琢磨一下,不难观察到,每一层的高度是这一层中所放书本的最大值,那么如果按照一定顺序插入书本,高度不就可以省略掉了吗?

因此,我们先把书本按高度从大到小排个序,这样每层的高度就是第一次插入到这层书的高度,于是状态又优化成了:\(dp[0/1][t1][t2]\)表示前i个,第一层宽度为t1,第二层宽度为t2,的最小三层总高度

转移的话就不用多说了吧。。。

代码:

注意一点,每层至少得有1本书,因此最后算面积时要排除某一层没有书的情况。(第二组样例已经良心地说明了这点)

#include<bits/stdc++.h>
using namespace std;
int n,dp[2][2110][2110],sum[101],ans=(1<<30);
struct node{
    int t,h;
}A[1010];
bool cmp(node A,node B){
    return A.h>B.h;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d %d",&A[i].h,&A[i].t);
    memset(dp,63,sizeof(dp));
    const int oo=dp[0][0][0];
    sort(A+1,A+1+n,cmp);
    for(int i=1;i<=n;i++)sum[i]=sum[i-1]+A[i].t;
    dp[0][0][0]=0;
    for(int i=1;i<=n;i++){
        int now=i&1,la=!now;
        memset(dp[now],63,sizeof(dp[now]));
        for(int j=0;j<=sum[i-1];j++){
            for(int k=0;k<=sum[i-1];k++){
                int o=sum[i-1]-j-k;
                if(o<0)continue;
                if(dp[la][j][k]==oo)continue;
                if(j==0)dp[now][j+A[i].t][k]=min(dp[now][j+A[i].t][k],dp[la][j][k]+A[i].h);
                else dp[now][j+A[i].t][k]=min(dp[now][j+A[i].t][k],dp[la][j][k]);
                if(k==0)dp[now][j][k+A[i].t]=min(dp[now][j][k+A[i].t],dp[la][j][k]+A[i].h);
                else dp[now][j][k+A[i].t]=min(dp[now][j][k+A[i].t],dp[la][j][k]);
                if(o==0)dp[now][j][k]=min(dp[now][j][k],dp[la][j][k]+A[i].h);
                else dp[now][j][k]=min(dp[now][j][k],dp[la][j][k]);
            }
        }
    }
    for(int i=1;i<=sum[n];i++){
        for(int j=1;j<=sum[n];j++){
            int o=sum[n]-i-j;
            if(o<=0)continue;
            if(dp[n&1][i][j]==oo)continue;
            ans=min(ans,max(max(i,j),o)*dp[n&1][i][j]);
        }
    }
    cout<<ans;
    return 0;
}

标签:h2,高度,t2,t3,t1,书柜,尺寸,SHOI2007,dp
来源: https://www.cnblogs.com/SillyTieT/p/11415298.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有