UVALive - 3637 The Bookcase

来源:互联网 发布:linux中touch创建用法 编辑:程序博客网 时间:2024/05/16 17:33

题意:有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;}




0 0
原创粉丝点击