UVA - 12099 The Bookcase(巧妙DP)

匿名 (未验证) 提交于 2019-12-03 00:26:01

思路:DP。

这里参考了网上的一种十分巧妙的dp方法,仅需要二维dp: dp[j][k]表示第二层宽度为j,第三层宽度为k的最小总高度(这两层的高度),若预处理总宽度的和sum,那剩下的那一层的宽度就是sum-j-k。我们假设第一层放高度最大的那本书,(如果不是,那我们就把放高度最高的那本书的那一层默认为第一层,这对结果是无影响的)

然后状态转移方程便十分简单了:(h表示高度,w表示宽度)

if(j>a[i].w)dp[j][k]=min(dp[j][k],dp[j-a[i].w][k]);
if(j==a[i].w)dp[j][k]=min(dp[j][k],dp[0][k]+a[i].h);
if(k>a[i].w)dp[j][k]=min(dp[j][k],dp[j][k-a[i].w]);

if(k==a[i].w)dp[j][k]=min(dp[j][k],dp[j][0]+a[i].h);

注意方程成立的前提是书的高度递减,所以要先排一下序,最后统计一下最小值即可。

代码:

#include<bits/stdc++.h> #define ll long long #define inf 0x3f3f3f3f using namespace std; const int maxn=2110; int n,m,k; int ans,tmp,cnt; int dp[maxn][maxn]; struct node {     int h,w;     bool operator<(node aa)const     {         return h>aa.h;     } }a[maxn]; int main() {     int T,cas=1;     scanf("%d",&T);     while(T--)     {         tmp=0;         scanf("%d",&n);         for(int i=1;i<=n;i++)         {             scanf("%d%d",&a[i].h,&a[i].w);             tmp+=a[i].w;         }         sort(a+1,a+1+n);         memset(dp,0x3f,sizeof(dp));         dp[0][0]=0;         for(int i=2;i<=n;i++)         {             for(int j=tmp;j>=0;j--)             for(int k=tmp;k>=0;k--)             {                 if(j>a[i].w)dp[j][k]=min(dp[j][k],dp[j-a[i].w][k]);                 if(j==a[i].w)dp[j][k]=min(dp[j][k],dp[0][k]+a[i].h);                 if(k>a[i].w)dp[j][k]=min(dp[j][k],dp[j][k-a[i].w]);                 if(k==a[i].w)dp[j][k]=min(dp[j][k],dp[j][0]+a[i].h);             }         }         ans=inf;         for(int i=tmp;i>0;i--)         for(int j=tmp;j>0;j--)         if(dp[i][j]<=900) ans=min(ans,(dp[i][j]+a[1].h)*max(max(i,j),tmp-i-j));         printf("%d\n",ans);     }     return 0; }

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!