tkj
文章143
标签102
分类0
bzoj 1933: [Shoi2007]Bookcase 书柜的尺寸

bzoj 1933: [Shoi2007]Bookcase 书柜的尺寸

.

题意:给出n本书的高度和厚度,把它们放在三行的书架上(每一行至少一本书),问书架正面的最小面积。
题解:先按高度从大到小排序,保证后面加入的书不会对高度造成影响,再dp。$f[i][j][k]$表示前i本书第一行的宽度为j,第三行的宽度为k的最小高度。

sum[i]表示前i本书的厚度和。第一维滚一下就好了。
代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int n,f[2][2200][2200],sum[80],ans=2147483647;
struct hh
{
    int h,t;
}a[80];

int cmp(hh x,hh y)
{
    return x.h>y.h;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&a[i].h,&a[i].t);
    }
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++)
    sum[i]=sum[i-1]+a[i].t;
    int p=0,q=1;
    for(int i=1;i<=n;i++)
    {
        p^=1;
        q^=1;
        memset(f[p],63,sizeof(f[p]));
        for(int j=0;j<=sum[i-1];j++)
        {
            for(int k=0;j+k<=sum[i-1];k++)
            {
                f[p][j+a[i].t][k]=min(f[p][j+a[i].t][k],f[q][j][k]+(j==0)*a[i].h);
                f[p][j][k+a[i].t]=min(f[p][j][k+a[i].t],f[q][j][k]+(k==0)*a[i].h);
                f[p][j][k]=min(f[p][j][k],f[q][j][k]+(j+k==sum[i-1])*a[i].h);
            }
        }
    }
    for(int i=1;i<sum[n];i++)
    {
        for(int j=1;i+j<sum[n];j++)
        if(f[p][i][j]<=1000)
        ans=min(ans,f[p][i][j]*max(i,max(j,sum[n]-i-j)));
    }
    printf("%d",ans);
}
本文作者:tkj
本文链接:https://tkj666.github.io/30/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可