列表

详情


NC20402. [SHOI2007]BOOKCASE 书柜的尺寸

描述

Tom不喜欢那种一字长龙式的大书架,他只想要一个小书柜来存放他的系列工具书。Tom打算把书柜放在桌子的后面,这样需要查书的时候就可以不用起身离开了。显然,这种书柜不能太大,Tom希望它的体积越小越好。另外,出于他的审美要求,他只想要一个三层的书柜。为了物尽其用,Tom规定每层必须至少放一本书。现在的问题是,Tom怎么分配他的工具书,才能让木匠造出最小的书柜来呢? 
Tom很快意识到这是一个数学问题。每本书都有自己的高度hi和厚度ti。我们需要求的是一个分配方案,也就是要求把所有的书分配在S1、S2和S3三个非空集合里面的一个,不重复也不遗漏,那么,很明显,书柜正面表面积(S)的计算公式就是:
   
由于书柜的深度是固定的(显然,它应该等于那本最宽的书的长度),所以要求书柜的体积最小就是要求S最小。Tom离答案只有一步之遥了。不过很遗憾,Tom并不擅长于编程,于是他邀请你来帮助他解决这个问题。

输入描述

文件的第一行只有一个整数n(3 ≤ n ≤ 70),代表书本的本数。
接下来有n行,每行有两个整数hi和ti,代表每本书的高度和厚度,我们保证150 ≤ hi ≤ 300,5 ≤ ti ≤ 30。

输出描述

只有一行,即输出最小的S。

示例1

输入:

4
220 29
195 20
200 9
180 30

输出:

18000

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 425ms, 内存消耗: 35056K, 提交时间: 2020-04-01 19:13:55

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,f[2][2101][2101],inf,kkz,sum[71],h,w,ans;
struct node
{
	int h,w;
}a[71];
bool operator <(node u,node v)
{
	return u.h>v.h;
}
int read()
{
	int totnum=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		totnum=(totnum<<1)+(totnum<<3)+ch-'0';
		ch=getchar();
	}
	return totnum*f;
}
int main()
{
	n=read();
	for(int i=1;i<=n;i++)
	a[i].h=read(),a[i].w=read();
	memset(f[kkz],127/3,sizeof(f[kkz]));
	ans=inf=f[kkz][0][0];
	f[kkz][0][0]=0;
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++)
	sum[i]=sum[i-1]+a[i].w;
	for(int i=1;i<=n;i++)
	{
		kkz^=1;
		h=a[i].h;
		w=a[i].w;
		memset(f[kkz],127/3,sizeof(f[kkz]));
		for(int j=sum[i-1];~j;j--)
		for(int k=sum[i-1];~k;k--)
		if(j+k<=sum[i-1]&&f[kkz^1][j][k]<inf)
		{
			if(j) f[kkz][j+w][k]=min(f[kkz][j+w][k],f[kkz^1][j][k]);
			else f[kkz][w][k]=min(f[kkz][j][k],f[kkz^1][j][k]+h);
			if(k) f[kkz][j][k+w]=min(f[kkz][j][k+w],f[kkz^1][j][k]);
			else f[kkz][j][w]=min(f[kkz][j][w],f[kkz^1][j][k]+h);
			if(j+k<sum[i-1]) f[kkz][j][k]=min(f[kkz][j][k],f[kkz^1][j][k]);
			else f[kkz][j][k]=min(f[kkz][j][k],f[kkz^1][j][k]+h);
		}
	}
	for(int i=1;i<sum[n];i++)
	for(int j=1;j<sum[n];j++)
	if(i+j<sum[n]&&f[kkz][i][j]<inf)
	ans=min(ans,max(max(i,j),sum[n]-i-j)*f[kkz][i][j]);
	printf("%d\n",ans);
	return 0;
}

上一题