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\n",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 }