• UVA


    No wonder the old bookcase caved under the massive piles of books Tom had stacked on it. He had better build a new one, this time large enough to hold all of his books. Tom finds it practical to have the books close at hand when he works at his desk. Therefore, he is imagining a compact solution with the bookcase standing on the back of the desk. Obviously, this would put some restrictions on the size of the bookcase, it should preferably be as small as possible. In addition, Tom would like the bookcase to have exactly three shelves for aesthetical reasons. Wondering how small his bookcase could be, he models the problem as follows. He measures the height hi and thickness ti of each book i and he seeks a partition of the books in three non-empty sets S1, S2, S3 such that (∑3 j=1 maxi∈Sj hi) × (max3 j=1 ∑ i∈Sj ti) is minimized, i.e. the area of the bookcase as seen when standing in front of it (the depth needed is obviously the largest width of all his books, regardless of the partition). Note that this formula does not give the exact area of the bookcase, since the actual shelves cause a small additional height, and the sides cause a small additional width. For simplicity, we will ignore this small discrepancy. Thinking a moment on the problem, Tom realizes he will need a computer program to do the job

    Input

    The input begins with a positive number on a line of its own telling the number of test cases (at most 20). For each test case there is one line containing a single positive integer N, 3 ≤ N ≤ 70 giving the number of books. Then N lines follow each containing two positive integers hi , ti , satisfying 150 ≤ hi ≤ 300 and 5 ≤ ti ≤ 30, the height and thickness of book i respectively, in millimeters. 

    Output

    For each test case, output one line containing the minimum area (height times width) of a three-shelf bookcase capable of holding all the books, expressed in square millimeters.

    Sample Input

    2

    4

    220 29

    195 20

    200 9

    180 30

    6

    256 20

    255 30

    254 15

    253 20

    252 15

    251 9

    Sample Output

    18000 29796

      这个题目在状态的构造上,十分用心,如果我们考虑暴力DP那么显然要记下6个东西,就是每行的长和高,当然首先空间上过不去,其次,转移也十分复杂,那么考虑优化我们的状态。

      首先只要记下两个宽和一个高就可以了,因为如果我们知道两个宽,就可以用总和减去两个宽得到下一个宽,然后有一个高是必定不用记下的,因为他一定是最高的那本书,然后第一维记处理到那本书,可以滚动,数组里存剩下的一个高,但即使优化到这个地步还是会暴空间!怎么办?

      我们把那两个高之和的最小值存在数组了,这样就只有三维(相当于两维),即:设dp[i][j][k],表示dp到第i本书,第二列的宽度是j,第三列的宽度是k的二三列的最小高度和,这个为什么可以转移呢?我们考虑将每本书按照高度排序!那么第一本(最高的一本)我们强制放在第一列,而且只要第二列,第三列有书,因为我们是从高到低放的所以一定更新不了最大当列的最高值,进而更新不了他们的高度和!

      转移就是枚举本书分放到第1,2,3,层进行转移。

    代码:

    #include<iostream>
    #include<stdio.h>
    #include<cstring>
    #include<algorithm>
    #include<stdlib.h>
    #define MAXN 2150
    #define ll long long
    using namespace std;
    struct book{
        int h,w;
    }a[80];
    int f[MAXN][MAXN],dp[2][MAXN][MAXN],sum[80];
    int n,inf;
    
    bool cmp(book x,book y){
        return x.h>y.h;
    }
    
    int main(){
        int t;cin>>t;
        while(t--){
            memset(f,0,sizeof(f));
            memset(dp,127,sizeof(dp));inf=dp[0][0][0];
            memset(a,0,sizeof(a));
            memset(sum,0,sizeof(sum));
            scanf("%d",&n);
            for(int i=1;i<=n;i++) scanf("%d%d",&a[i].h,&a[i].w);
            sort(a+1,a+n+1,cmp);
            for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i].w;
            for(int i=1;i<=n;i++){
                f[0][a[i].h]=a[i].h;
            }
            dp[0][0][0]=0;
            int now=0,last=1;
            for(int i=1;i<n;i++){
                now^=1,last^=1;
                memset(dp[now],127,sizeof(dp[now]));
                for(int j=0;j<=sum[i];j++)
                    for(int k=0;k<=sum[i];k++){
                        if(dp[last][j][k]==inf) continue;
                        if(j+k>sum[i]) break;
                        dp[now][j+a[i+1].w][k]=min(dp[now][j+a[i+1].w][k],dp[last][j][k]+f[j][a[i+1].h]);
                        dp[now][j][k+a[i+1].w]=min(dp[now][j][k+a[i+1].w],dp[last][j][k]+f[k][a[i+1].h]);
                        dp[now][j][k]=min(dp[now][j][k],dp[last][j][k]);
                    }
            }
            int ans=inf;
            for(int i=0;i<=sum[n];i++)
            for(int j=0;j<=sum[n];j++){
                if(i+j>sum[n]) break;
                if(dp[now][i][j]==inf) continue;
                if(i == 0 || j == 0)  continue;
                ans = min(ans, (dp[now][i][j] + a[1].h) * max(j, max(i, sum[n]-j-i)));
            }
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    js循环
    js对象
    实现checkebox全选取消操作
    js数组
    jquery记忆笔记
    js选择checkbox值,组织成key-value形式,传值到后台
    ES6常用语法,面试应急专用!
    Win10 系统运行VsCode出现白屏的问题(亲测有效)
    command failed: npm install --loglevel error --registry=https://registry.npm 用vue-cli 4.0 新建项目总是报错
    MODULE BUILD FAILED: ERROR: COULDN’T FIND PRESET “ES2015” RELATIVE TO DIRECTORY
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7448400.html
Copyright © 2020-2023  润新知