UVALive 3637 The Bookcase

题目大意:有 n (3 <= n <= 70)本书,现在有一个书架,书架有三层,要把 n 本书放到书架上,每层不能为空,每本书有高度和宽度, hi 和 ti ,要使这个最小,问你这个最小值。

思路:设 d[ i ][ i ][ j ] 表示前 i 本,第二层的 t 和为 j,第三层的 t 和为 k  的二三层的最大高度之和的最小值。我们先把所有书按照高度从大到小排序,则每进来一本,只要该层的不为空,则这本书的高度就不会影响到 d 值,也就是每层的高度只取决于该层放进来的第一本书,每本书只有三种选择,放第一层,或者第二层,或者第三层,则 d[ i ][ j ][ k ] = min(d[ i- 1 ][ j ][ k  - book[ i ].t] + book[i].h,d[i - 1][ j ][ k ]) ,k == book[i].t;d[ i ][ j ][ k] = min(d[i - 1][ j - book[i].t][ k ] + book[i].h,d[ i- 1 ][ j ][ k ]) ,j == book[i].t;d[ i ][ j ][ k ] = min(d[ i - 1][ j ][ k ] ,d[ i - 1 ][ j - book[i].t ][ k ],d[ i - 1 ][ j ][ k - book[i].t ]),j > book[i].t,k > book[i].t 。知道了第二、三层的 t 和,那么第一层就是s- i - j,关键还在于第一层的 h 。这里我们考虑把高度最大的一本书放在第一层,即排序后的 book[ 1 ],然后DP的时候从 i = 2 开始,所以答案就是 min(  (d[ n ][ i ][ j ] + book[1].h) *max(i , j , s - i - j) )。由于空间问题,这里还需要用滚动数组来优化空间。

这题的DP真心不好想,原来只需要三个维度就可以了,从小到大排序,之后的不影响高度,第三个的 t 和可以减一下,还有DP从 2 开始,把第一本书放在第一层这些,哎,真心想不到,继续多练吧。。~~~~(>_<)~~~~

 代码如下:

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

typedef pair<int,int> pii;

#define MP make_pair

const int INF = 0x0fffffff ;

const int MAXN = 77;

pii book[MAXN];

int cmp(pii a,pii b)
{
    return a.first > b.first ;
}

int d[2222][2222];

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        int sum_w = 0;
        for(int i = 1;i<=n;i++)
        {
        	int a,b;
         	scanf("%d%d",&a,&b);
          	book[i] = MP(a,b);
          	sum_w += b;
        }
        sort(book + 1,book + 1 + n ,cmp);
        for(int i = 0;i<=sum_w;i++)
            for(int j = 0;j<=sum_w;j++)
                d[i][j] = INF;
        d[0][0] = 0;
        for(int i = 2;i<=n;i++)
        {
        	for(int j = sum_w;j>=0;j--)
        		for(int k = sum_w;k>=0;k--)
        		{
           			if(book[i].second == j) d[j][k] = min(d[j][k] , d[0][k] + book[i].first);
           			if(book[i].second == k) d[j][k] = min(d[j][k] , d[j][0] + book[i].first);
              		if(j > book[i].second) d[j][k] = min(d[j][k],d[j - book[i].second][k]);
              		if(k > book[i].second) d[j][k] = min(d[j][k],d[j][k - book[i].second]);
                 }
		}
  		int ans = INF;
    	for(int i = 1;i<sum_w;i++)
     		for(int j = 1;j<sum_w;j++)
       		{
         		if(d[i][j] >= INF) continue;
           		int w = max(max(i,j),sum_w - i - j);
             	int h = d[i][j] + book[1].first;
              	ans = min(ans,w*h);
           	}
		printf("%d\n",ans);
    }
    return 0;
}


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