pku3124 The Bookcase 扩展背包好题

pku3124 The Bookcase 扩展背包好题

题意:
一堆书,每本书都有厚度和高度,管理员试图将这些书放到三层的书架上,每层都不能为空,求书架最小体积(书架深度显然为所有书深度最大值,所以与排放方案无关,故取1).
体积公式:
解题思想:
大概思路是DP,这个要先定下来
设v=(f(s1)+f(s2)+f(s3))*max{g(s1),g(s2),g(s3)}
其中g(s3)=SUM-g(s1)-g(s2)
f(s3)=max(h i)
就说说,我们有4个决策变量
一个变量留给DP决策,另一个变量利用DP状态设计来消除(这就需要对初始数据排序,保证决策过程中h i<=h p2,i属于s2,p2为当前决策点)。
这个问题就转化为在一个有序队列上选择两个分割点p1,p2,h p1<h p2,使得max{hi,i属于s1}<p1,max{hi,i属于s2}<p2,并且s1,s2,s3均不为空
状态可以设计为
F(i,t 1,t 2)
即考虑到第i个元素,s1的总厚度为t1,s2的总厚度为t2时p1所在元素的高度的最小值。
F(i,t1,t2)=min(F(i-1,t1,t2-data[i].t),data[i].h(当F(i-1,t1-data[i].t,t2)合法时),F(i-1,t1,t2)),显然,三个转移意义分别为将当前元素分配给s2、s1、s3
当F(i,t1,t2)由F(i-1,t1,t2-data[i].t)转移过来的时候试图更新全局最优解ans=min(ans,(data[i].h+F(i,t1,t2)+data[n-1].h)*t1*t2*(t total-t1-t2))。注意,这里说F(i,t1,t2)由F(i-1,t1,t2-data[i].t)转移过来指的是F(i-1,t1,t2-data[i].t)<=min(data[i].h(当F(i-1,t1-data[i].t,t2)合法时),F(i-1,t1,t2)),等于不能丢掉(原因?只有此时才能更新全局最优解)
代码如下

 1 Source Code
 2 
 3 Problem: 3124        User: yzhw
 4 Memory: 17744K        Time: 2188MS
 5 Language: G++        Result: Accepted
 6 Source Code
 7 # include <cstdio>
 8 # include <utility>
 9 # include <functional>
10 # include <cstring>
11 # include <vector>
12 # include <algorithm>
13 using namespace std;
14 # define M 2105
15 # define N 100
16 int dp[M][M],n,total,ans,sum[N];
17 pair<int,int> data[N];
18 bool cmp(const pair<int,int> &a,const pair<int,int> &b)
19 {
20     return a.first<b.first;
21 }
22 
23 int main()
24 {
25     //freopen("bookcase.in","r",stdin);
26     int test;
27     scanf("%d",&test);
28     for(int t=1;t<=test;t++)
29     {
30         scanf("%d",&n);
31         total=0;
32         ans=0xfffffff;
33         for(int i=1;i<=n;i++)
34         {
35             scanf("%d%d",&data[i].first,&data[i].second);
36             total+=data[i].second;
37         }
38         sort(data+1,data+n+1,cmp);
39         sum[0]=0;
40         for(int i=1;i<=n;i++)
41             sum[i]=sum[i-1]+data[i].second;
42         memset(dp,-1,sizeof(dp));
43         dp[0][0]=0;
44         for(int i=1;i<=n;i++)
45         {
46             for(int j=sum[i-1];j>=0;j--)
47                 for(int k=sum[i-1];k>=0;k--)
48                     if(dp[j][k]!=-1)
49                     {
50                         if(dp[j+data[i].second][k]==-1||dp[j+data[i].second][k]>data[i].first)
51                             dp[j+data[i].second][k]=data[i].first;
52                         if(dp[j][k+data[i].second]==-1||dp[j][k+data[i].second]>=dp[j][k])
53                         {
54                             dp[j][k+data[i].second]=dp[j][k];
55                             if(j&&j+k+data[i].second!=total)
56                                 ans=min(ans,(dp[j][k]+data[i].first+data[n].first)*max(j,max(k+data[i].second,total-j-k-data[i].second)));
57                         }
58                     }
59         }
60         printf("%d\n",ans);
61 
62     }
63     return 0;
64 
65 

你可能感兴趣的:(pku3124 The Bookcase 扩展背包好题)