HDU 3535 AreYouBusy(分组DP)

HDU 3535  AreYouBusy

题解:dp[i][j]表示的是在第i组剩余时间为j时的快乐值,我们需要对每一组工作进行一次DP。

第一类:即s==0时,表示该组中工作必须要选且至少选一项。为了保证不出现不选的现象,我们应该把DP数组初始化为负无穷。状态转移方程为: dp[i][k]=max(dp[i][k],max(dp[i-1][k-c[j]]+val[j],dp[i][k-c[j]]+val[j])); dp[i][k]表示不选该组中的第j个工作,dp[i-1][k-c[j]]+val[j]表示选第j项工作且是第一次在本组中选。dp[i][k-c[j]]+val[j])表示选第j项工作且不是第一次在本组中选。

第二类:即s==1时,最多选一项,即要么不选,一旦选,只能是第一次选。状态转移方程为:  dp[i][k]=max(dp[i][k],dp[i-1][k-c[j]]+val[j]) 由于要保证得到全局最优解,所以在该组DP开始以前,应该将上一组的DP结果先复制到这一组的dp[i]数组里,因为这一组的数据是在上一组数据的基础上进行更新的。

第三类:即s==2时,任意选,即不论选不选,选几次都可以。状态转移方程与第一类一致,不同的在于第三类对dp的初始化为上一组的值,而不是初始化为负无穷。

最近又理解了一下:至少选一个时,将当前组的dp全部赋值为-inf,以保证一定能选,最多选一个和随便选时,将上一组的dp值复制到当前组,表示的意思是当前组一个都不选,最多选一个,需要由上一组的值来更新,即

选就一定是在本组第一次选:dp[i][k]=max(dp[i][k],dp[i-1][k-c[j]]+val[j]) 而随便选则为一个简单的01背包,可写成dp[i][k]=max(dp[i][k],dp[i][k-c[j]]+val[j])。 新代码在下面。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define inf -0x3f3f3f3f
 6 using namespace std;
 7 const int maxn=110;
 8  
 9 int n,t;
10 int dp[maxn][maxn];
11 int m,s,c[maxn],val[maxn];
12 int main()
13 {
14     while(~scanf("%d%d",&n,&t))
15     {
16         memset(dp,0,sizeof(dp));
17         for(int i=1;i<=n;i++)
18         {
19             scanf("%d%d",&m,&s);
20             for(int j=1;j<=m;j++)
21                 scanf("%d%d",&c[j],&val[j]);
22             if(s==0)
23             {
24                 for(int j=0;j<=t;j++)
25                     dp[i][j]=inf;
26                 for(int j=1;j<=m;j++)
27                 {
28                     for(int k=t;k>=c[j];k--)
29                     {
30                         dp[i][k]=max(dp[i][k],max(dp[i-1][k-c[j]]+val[j],dp[i][k-c[j]]+val[j]));
31                     }
32                 }
33             }
34             else if(s==1)
35             {
36                 for(int j=0;j<=t;j++)
37                 {
38                     dp[i][j]=dp[i-1][j];
39                 }
40                 for(int j=1;j<=m;j++)
41                 {
42                     for(int k=t;k>=c[j];k--)
43                     {
44                         dp[i][k]=max(dp[i][k],dp[i-1][k-c[j]]+val[j]);
45                     }
46                 }
47             }
48             else if(s==2)
49             {
50                 for(int j=0;j<=t;j++)
51                 {
52                     dp[i][j]=dp[i-1][j];
53                 }
54                 for(int j=1;j<=m;j++)
55                 {
56                     for(int k=t;k>=c[j];k--)
57                     {
58                         dp[i][k]=max(dp[i][k],max(dp[i-1][k-c[j]]+val[j],dp[i][k-c[j]]+val[j]));
59                     }
60                 }
61             }
62     
63         }
64         dp[n][t]=max(dp[n][t],-1);
65         printf("%d
",dp[n][t]);
66     }
67 return 0;
68 }
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<stack>
 5 #include<algorithm>
 6 #define inf 0x3f3f3f3f
 7 using namespace std;
 8 const int maxn=200100;
 9 int dp[110][110];
10 int c[110],val[110];
11 int n,t;
12 int maxx(int a,int b,int c)
13 {
14     int t=a>b?a:b;
15     return t>c?t:c;
16 }
17 int main()
18 {
19     while(~scanf("%d%d",&n,&t))
20     {
21         memset(dp,0,sizeof(dp));
22         int type,m;
23         for(int i=1;i<=n;i++)
24         {
25             scanf("%d%d",&m,&type);
26             for(int j=1;j<=m;j++)
27             {
28                 scanf("%d%d",&c[j],&val[j]);
29             }
30             if(type==0)
31             {
32                 for(int j=0;j<=t;j++)
33                     dp[i][j]=-inf;
34                 for(int j=1;j<=m;j++)
35                 {
36                     for(int k=t;k>=c[j];k--)
37                     {
38                         dp[i][k]=maxx(dp[i][k],dp[i-1][k-c[j]]+val[j],dp[i][k-c[j]]+val[j]);
39                     }
40                 }
41 
42             }
43             else if(type==1)
44             {
45                 for(int j=0;j<=t;j++)
46                     dp[i][j]=dp[i-1][j];
47                 for(int j=1;j<=m;j++)
48                 {
49                     for(int k=t;k>=c[j];k--)
50                     {
51                         dp[i][k]=max(dp[i][k],dp[i-1][k-c[j]]+val[j]);
52                     }
53                 }
54             }
55             else
56             {
57                 for(int j=0;j<=t;j++)
58                     dp[i][j]=dp[i-1][j];
59                 for(int j=1;j<=m;j++)
60                 {
61                     for(int k=t;k>=c[j];k--)
62                     {
63                         dp[i][k]=max(dp[i][k],dp[i][k-c[j]]+val[j]);
64                     }
65                 }
66             }
67         }
68        if(dp[n][t]>0)
69             cout<<dp[n][t]<<endl;
70        else
71             cout<<-1<<endl;
72     }
73 return 0;
74 }
原文地址:https://www.cnblogs.com/1013star/p/9489344.html