UVALive - 3637 The Bookcase

题意:有n本书,没本书有一个高度Hi和宽度Wi,现在要构建一个3层的书架,你可以选择将n本书放在书架的哪一层,设3层高度和(该层的书的最大高度)为h,书架总宽度为(该层的书的最大宽度)w,,要求h*w最小

思路:不太好想的DP,但想到了也就没那么难了,首先将书按高度从大到小排序依次放,然后dp[i][j]表示第二层的宽度是i第三层的宽度是j的最小高度,问题有来了,怎么转移方程呢,不好想的就枚举状态吧,枚举第二三层的高度,如果他是该层的第一本的话,那么就只是增加了宽度,否则的话还增加了高度

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int MAXN = 2500;
const int INF = 0x3f3f3f3f;

struct book{
    int h,w;
}p[100];
int dp[MAXN][MAXN],n;

bool cmp(book a,book b){
    return a.h > b.h;
}

int main(){
    int t;
    scanf("%d",&t);
    while (t--){
        scanf("%d",&n);
        int tot = 0;
        for (int i = 0; i < n; i++){
            scanf("%d%d",&p[i].h,&p[i].w);
            tot += p[i].w;
        }
        sort(p,p+n,cmp);
        for (int i = 0; i <= tot; i++)
            for (int j = 0; j <= tot; j++)
                dp[i][j] = INF;
        dp[0][0] = 0;
        for (int k = 1; k < n; k++){
            for (int i = tot; i >= 0; i--)
                for (int j = tot; j >= 0; j--){
                    if (dp[i][j] != INF){
                        if (i == 0)
                            dp[i+p[k].w][j] = min(dp[i+p[k].w][j],dp[i][j]+p[k].h);
                        else dp[i+p[k].w][j] = min(dp[i+p[k].w][j],dp[i][j]);
                        if (j == 0)
                            dp[i][j+p[k].w] = min(dp[i][j+p[k].w],dp[i][j]+p[k].h);
                        else dp[i][j+p[k].w] = min(dp[i][j+p[k].w],dp[i][j]);
                        
                    }
                }
        }
        int ans = INF;
        for (int i = 1; i <= tot; i++)
            for (int j = 1; j <= tot; j++){
                if (dp[i][j] != INF){
                    int w = max(i,j);
                    w = max(w,tot-i-j);
                    ans = min(ans,(dp[i][j]+p[0].h)*w);
                }
            }
        printf("%d\n",ans);
    }
    return 0;
}




你可能感兴趣的:(UVALive - 3637 The Bookcase)