给一个三层的书架以及n本书 已知书的高度和宽 求书架的最小面积
状态转移十分奇葩 参考了大神的题解
dp[i][j] 表示当第二个书架的宽为i第三个宽为j的时候的最小高度和,默认第一个书架为最高的书本
首先要对书进行排序,这样使得问题简单化一点
然后对于状态转移方程见代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0xffffff
struct dota{
int h,t;
}data[700];
int dp[2200][2200];
int cmp(dota a,dota b)
{
return a.h>b.h;
}
int main ()
{
int t;
scanf ("%d",&t);
while (t--)
{
int n;
scanf ("%d",&n);
int sum=0;
for(int i=0;i<n;i++)
{
scanf("%d%d",&data[i].h,&data[i].t);
sum+=data[i].t;
}
sort(data,data+n,cmp);
for(int i=0;i<=sum;i++)
for(int j=0;j<=sum;j++)
dp[i][j]=INF;
sum=0;
dp[0][0]=0;
for(int i=1;i<n;i++)
{
sum+=data[i].t;
for(int j=sum;j>=0;j--)
{
for(int k=sum;k>=0;k--)
{
if(j-data[i].t>0&&dp[j-data[i].t][k]<dp[j][k])
dp[j][k]=dp[j-data[i].t][k];
if(j-data[i].t==0&&dp[0][k]+data[i].h<dp[j][k])
dp[j][k]=dp[0][k]+data[i].h;
if(k-data[i].t>0&&dp[j][k-data[i].t]<dp[j][k])
dp[j][k]=dp[j][k-data[i].t];
if(k-data[i].t==0&&dp[j][0]+data[i].h<dp[j][k])
dp[j][k]=dp[j][0]+data[i].h;
}
}
}
int ans=0x7fffffff;
for(int i=1;i<=sum;i++)
for(int j=1;j<=sum;j++)if(dp[i][j]!=INF)
{
int tmp=(dp[i][j]+data[0].h)*max(sum-i-j+data[0].t,max(i,j));
ans=ans<tmp?ans:tmp;
}
printf("%d\n",ans);
}
}