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的初始化为上一组的值,而不是初始化为负无穷。

 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\n",dp[n][t]);
66     }
67 return 0;
68 }

猜你喜欢

转载自www.cnblogs.com/1013star/p/9489344.html
今日推荐