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
",ans);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Achenchen/p/7612025.html