题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3496
题意:有n部电影,给出他们的用时和价值,现在一定要看m部(不能多不能少),花的时间要少于等于l,问最大价值
题解:二维01背包问题,由于一定要看m部,要注意初值问题
我的写法:
1 #include <cstdio>
2 #include <cstring>
3 #define N 105
4 #define L 1005
5
6 int dp[N][N][L], time[N], value[N];
7 int main()
8 {
9 int n, m, l, t;
10 scanf("%d",&t);
11 while(t--)
12 {
13 scanf("%d%d%d",&n, &m, &l);
14 for(int i=1; i<=n; i++)
15 scanf("%d%d",&time[i],&value[i]);
16 memset(dp, -1, sizeof(dp));
17 //for(int i=0; i<=m; i++)
18 dp[0][0][0] = 0;
19 for(int i=1; i<=n; i++)
20 {
21 for(int j=0; j<=m; j++)
22 {
23 for(int k=0; k<=l; k++)
24 {
25 if(dp[i][j][k] < dp[i-1][j][k]) dp[i][j][k] = dp[i-1][j][k];
26 if(dp[i-1][j][k]==-1 || k+time[i]>l || j+1>m) continue;
27 if(dp[i-1][j][k]+value[i]>dp[i][j+1][k+time[i]])
28 dp[i][j+1][k+time[i]] = dp[i-1][j][k]+value[i];
29 }
30 }
31 }
32
33 int ans = 0;
34 for(int i=0; i<=l; i++)
35 {
36 if(ans<dp[n][m][i])
37 ans = dp[n][m][i];
38 }
39 printf("%d ",ans);
40 }
41 return 0;
42 }
2 #include <cstring>
3 #define N 105
4 #define L 1005
5
6 int dp[N][N][L], time[N], value[N];
7 int main()
8 {
9 int n, m, l, t;
10 scanf("%d",&t);
11 while(t--)
12 {
13 scanf("%d%d%d",&n, &m, &l);
14 for(int i=1; i<=n; i++)
15 scanf("%d%d",&time[i],&value[i]);
16 memset(dp, -1, sizeof(dp));
17 //for(int i=0; i<=m; i++)
18 dp[0][0][0] = 0;
19 for(int i=1; i<=n; i++)
20 {
21 for(int j=0; j<=m; j++)
22 {
23 for(int k=0; k<=l; k++)
24 {
25 if(dp[i][j][k] < dp[i-1][j][k]) dp[i][j][k] = dp[i-1][j][k];
26 if(dp[i-1][j][k]==-1 || k+time[i]>l || j+1>m) continue;
27 if(dp[i-1][j][k]+value[i]>dp[i][j+1][k+time[i]])
28 dp[i][j+1][k+time[i]] = dp[i-1][j][k]+value[i];
29 }
30 }
31 }
32
33 int ans = 0;
34 for(int i=0; i<=l; i++)
35 {
36 if(ans<dp[n][m][i])
37 ans = dp[n][m][i];
38 }
39 printf("%d ",ans);
40 }
41 return 0;
42 }
用现在枚举到的状态去更新前面的状态。
dp[i][j+1][k+time[i]] = max(dp[i-1][j][k]+value[i], dp[i][j+1][k+time[i]])
this:
1 #include<stdio.h>
2 #include<string.h>
3 #define INF 0xffffff
4 int dp[105][1005],time[105],val[105];
5 int MAX(int a,int b)
6 {
7 if(a>b) return a;
8 return b;
9 }
10 int main()
11 {
12 int t,i,j,k,n,m,l;
13
14 scanf("%d",&t);
15 while(t--)
16 {
17 scanf("%d%d%d",&n,&m,&l);
18 for(i=0;i<n;i++) scanf("%d%d",time+i,val+i);
19 for(i=0;i<=l;i++) dp[0][i]=0;
20 for(i=1;i<=m;i++)
21 for(j=0;j<=l;j++)
22 dp[i][j]=-INF;
23
24 for(i=0;i<n;i++)
25 {
26 for(j=m;j>0;j--)
27 {
28 for(k=l;k>=time[i];k--)
29 {
30 if(dp[j-1][k]==-INF) continue;
31 dp[j][k]=MAX(dp[j][k],dp[j-1][k-time[i]]+val[i]);
32 }
33 }
34 }
35 if(dp[m][l]>0) printf("%d ",dp[m][l]);
36 else printf("0 ");
37 }
38
39 return 0;
40 }
2 #include<string.h>
3 #define INF 0xffffff
4 int dp[105][1005],time[105],val[105];
5 int MAX(int a,int b)
6 {
7 if(a>b) return a;
8 return b;
9 }
10 int main()
11 {
12 int t,i,j,k,n,m,l;
13
14 scanf("%d",&t);
15 while(t--)
16 {
17 scanf("%d%d%d",&n,&m,&l);
18 for(i=0;i<n;i++) scanf("%d%d",time+i,val+i);
19 for(i=0;i<=l;i++) dp[0][i]=0;
20 for(i=1;i<=m;i++)
21 for(j=0;j<=l;j++)
22 dp[i][j]=-INF;
23
24 for(i=0;i<n;i++)
25 {
26 for(j=m;j>0;j--)
27 {
28 for(k=l;k>=time[i];k--)
29 {
30 if(dp[j-1][k]==-INF) continue;
31 dp[j][k]=MAX(dp[j][k],dp[j-1][k-time[i]]+val[i]);
32 }
33 }
34 }
35 if(dp[m][l]>0) printf("%d ",dp[m][l]);
36 else printf("0 ");
37 }
38
39 return 0;
40 }
用前面的状态更新现枚举到在的状态
数组值初始化为无限大,可使恰好背包容量为恰好装满。
- if(dp[j-1][k]==-INF) continue;
- dp[j][k]=MAX(dp[j][k],dp[j-1][k-time[i]]+val[i]);