codeforces - 148E 题解

题目大意:一个公主有一个摆满瓷器的架子,她生气的时候就要打碎m个瓷器。这个架子有n层,每层的瓷器每次只能从最左边拿或者从最右边拿,问打碎的瓷器的最大价值。

题解:这是一个分组背包的DP,首先将每一层上拿出瓷器的方案作为一个物品,拿出瓷器的方案的代价是瓷器数量,价值是这一层上所有方案中最大的价值。

首先为了计算方案的时候可以快速计算,我们在读入的时候就计算出前缀和sum,然后在计算方案的时候,每一层上打碎的数量对应一个物品,然后枚举总数量分配到两侧打碎的价格,得到最大价值。最后使用分组背包解决。

分组背包常见代码:

K代表有K个组,V是背包最大容量,这里要注意在最里面要防止v-ci小于0,否则会出现未定义行为,导致计算错误

for k 1 to K
  for v V to 0
    for all item i in group k
      F[v]=max(F [v], F [v - Ci] + Wi);

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<vector>
 6 using namespace std;
 7 struct datatype
 8 {
 9     int value;
10     int space;
11 };
12 vector<datatype> a[101];
13 int shelf[101][101];
14 int sum[101][101];
15 int amount[101];
16 int f[10001];
17 int main()
18 {
19     int n,m;
20     scanf("%d%d",&n,&m);
21     memset(sum,0,sizeof(sum));
22     for(int i=1;i<=n;i++)
23     {
24         int x;
25         scanf("%d",&x);
26         amount[i]=x;
27         for(int j=1;j<=x;j++)
28         {
29             scanf("%d",&shelf[i][j]);
30             sum[i][j]=sum[i][j-1]+shelf[i][j];
31         }
32     }
33     for(int i=1;i<=n;i++)
34     {
35         for(int k=1;k<=amount[i];k++)
36         {
37             datatype tmp;
38             tmp.space=k;
39             tmp.value=0;
40             for(int j=0;j<=k;j++)
41             {
42                 int tmp_v=0;
43                 tmp_v+=sum[i][j];
44                 tmp_v+=sum[i][amount[i]]-sum[i][amount[i]-(k-j)];
45                 tmp.value=max(tmp_v,tmp.value);
46             }
47             a[i].push_back(tmp);
48         }
49     }
50     memset(f,0,sizeof(f));
51     for(int i=1;i<=n;i++)
52     {
53         for(int j=m;j>=0;j--)
54         {
55             vector<datatype>::iterator it;
56             for(it=a[i].begin();it!=a[i].end();it++)
57             {
58                 if(j-(*it).space<0)
59                 {
60                     continue;
61                 }
62                 f[j]=max(f[j],f[j-(*it).space]+(*it).value);
63             }
64         }
65     }
66     printf("%d\n",f[m]);
67     return 0;
68 }

 

转载于:https://www.cnblogs.com/shao0099876/p/7400316.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值