uestc1218_变形01背包

题目链接:http://acm.uestc.edu.cn/#/problem/show/1218

题目大意:给出n根木棒的长度和价值,最多可以装在一个长 l 的容器中,相邻木棒之间不允许重叠,且两边上的木棒,可以伸一半的长度在容器外,求最大价值量

解题思路:初看一眼就是01背包,没错就是01背包,但是有个特殊的地方需要处理,就是容器2边的筷子,将容器的长度X2,筷子的长度X2,那么相当于每根筷子的价值,可以被放0,1,2次,再加一层循环来枚举放筷子的价值量

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cstdio>
 6 #include <vector>
 7 #include <ctime>
 8 #include <queue>
 9 #include <list>
10 #include <set>
11 #include <map>
12 using namespace std;
13 #define INF 0x3f3f3f3f
14 typedef long long LL;
15 
16 LL dp[4010][3], val[1010], w[1010];
17 int main()
18 {
19     int t, n, l;
20     scanf("%d", &t);
21     for(int ca = 1; ca <= t; ca++)
22     {
23         scanf("%d %d", &n, &l);
24         LL res = 0;
25         for(int i = 1; i <= n; i++)
26         {
27             scanf("%lld %lld", &w[i], &val[i]);
28             res = max(res, val[i]);//只放一根的最大价值
29             w[i] <<= 1;
30         }
31         l <<= 1;
32         memset(dp, 0, sizeof(dp));
33         for(int i = 1; i <= n; i++)
34         {
35             for(int j = l; j >= w[i] / 2; j--)
36             {
37                 for(int k = 0; k < 3; k++)//有几根木棒是在外面的,最多两根,所以k <= 2
38                 {
39                     if(k >= 1)
40                         dp[j][k] = max(dp[j][k], dp[j-w[i]/2][k-1]+val[i]);  //当前木棒放外面
41                     if(j >= w[i])
42                         dp[j][k] = max(dp[j][k], dp[j-w[i]][k]+val[i]); //当前木棒全部在里面
43                 }
44             }
45         }
46         for(int i = 0; i < 3; i++)
47             res = max(res, dp[l][i]);
48         printf("Case #%d: %lld
", ca, res);
49     }
50     return 0;
51 }
View Code
原文地址:https://www.cnblogs.com/luomi/p/5901552.html