题目大意:
有n(3≤n≤70)n(3leq nleq 70)n(3≤n≤70)本书,每本书有一个高度HiH_iHi和一个宽度Wi(150≤Hi≤300,5≤Wi≤30)W_i(150leq H_ileq 300,5leq W_ileq 30)Wi(150≤Hi≤300,5≤Wi≤30)。 现在要构建一个3层的书架,你可以选择将nnn本书放在书架的哪一层。设3层高度(该层书的最大高度)之和为hhh,书架总宽度为www,要求h×wh imes wh×w(书架的面积)尽量小。
输入格式:
输入包含多组数据(不多于20个); 对于每组数据,第一行有一个正整数nnn,书的数量; 接下来nnn行每行两个正整数hi,wih_i,w_ihi,wi,分别代表书的高度、书的宽度。
输出格式:
对于每组测试数据,输出一行一个正整数,表示书架的最小面积。
输入样例:
2 4 220 29 195 20 200 9 180 30 6 256 20 255 30 254 15 253 20 252 15 251 9
输出样例:
18000 29796
f[i][j][k]表示前i个书摆好后,第2层宽度为j,第3层宽度为k的最小高度和
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; const int maxn = 2210; int f[2][maxn][maxn],n,sumw[maxn]; struct node { int h,w; bool operator <(const node& a) const{ return h>a.h; } }book[maxn]; int main() { //freopen("in.txt","r",stdin); int t;scanf("%d",&t); while(t--) { scanf("%d",&n); sumw[0]=0; for(int i=1;i<=n;i++) { scanf("%d%d",&book[i].h,&book[i].w); } sort(book+1,book+1+n); for(int i=1;i<=n;i++) sumw[i]=sumw[i-1]+book[i].w; for(int hh=0;hh<=1;hh++) for(int i=0;i<=sumw[n];i++) for(int j=0;j+i<=sumw[n];j++) f[hh][i][j]=610; f[1][0][0]=0; for(int i=2;i<=n;i++) { for(int j=0;j<=sumw[i];j++){ for(int k=0;k+j<=sumw[i];k++) { f[i%2][j][k]=f[(i-1)%2][j][k]; if(j-book[i].w>=0)f[i%2][j][k]=min(f[i%2][j][k],f[(i-1)%2][j-book[i].w][k]+(j-book[i].w==0?book[i].h:0)); if(k-book[i].w>=0)f[i%2][j][k]=min(f[i%2][j][k],f[(i-1)%2][j][k-book[i].w]+(k-book[i].w==0?book[i].h:0)); } } } int ans=inf; for(int i=1;i<=sumw[n];i++) { for(int j=1;j+i<=sumw[n];j++) { if(f[n%2][i][j]!=610) ans=min(ans,(f[n%2][i][j]+book[1].h)*max(i,max(j,sumw[n]-i-j))); } } printf("%d ",ans); } return 0; }