传送门

题意

给出n个体积为wi,价值为ci的物品,现在有一个m大的背包

问如何装使得最后背包内的物品价值最大,输出价值

分析

一般的思路是01背包,但n*v不可做

题解的思路

We can iterate on the number of 3-elements we will take (in this editorial k-element is a souvenir with weight k). When fixing the number of 3-elements (let it be x), we want to know the best possible answer for the weight m - 3x, while taking into account only 1-elements and 2-elements.

To answer these queries, we can precalculate the values dp[w] — triples (cost, cnt1, cnt2), where cost is the best possible answer for the weight w, and cnt1 and cnt2 is the number of 1-elements and 2-elements we are taking to get this answer. Of course, dp[0] = (0, 0, 0), and we can update dp[i + 1] and dp[i + 2] using value of dp[i]. After precalculating dp[w] for each possible w we can iterate on the number of 3-elements.

这道题我还没有真正理解,留坑

trick

代码

#include <cstdio>
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <string>
#include <cstring>
#include <sstream>
#include <algorithm>
using namespace std; typedef long long ll; const int Maxm = 300015;
const int Maxw = 3; int n, m;
ll best[Maxm];
vector <int> seq[Maxw]; ll Solve()
{
int i = 0, j = 0;
ll cur = 0, w = 0;
ll res = best[m];
if (i < seq[0].size() && 1 <= m) res = max(res, seq[0][i] + best[m - 1]);
while (i + 2 <= seq[0].size() || j + 1 <= seq[1].size()) {
if (i + 2 <= seq[0].size() && (j + 1 > seq[1].size() || seq[0][i] + seq[0][i + 1] > seq[1][j])) {
cur += seq[0][i] + seq[0][i + 1]; w += 2; i += 2;
} else {
cur += seq[1][j]; w += 2; j++;
}
if (w <= m) res = max(res, cur + best[m - w]);
if (w + 1 <= m) {
if (i < seq[0].size()) res = max(res, cur + ll(seq[0][i]) + best[m - w - 1]);
if (i > 0 && j < seq[1].size()) res = max(res, cur + ll(seq[1][j]) - ll(seq[0][i - 1]) + best[m - w - 1]);
}
}
return res;
} int main()
{
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++) {
int w, c; scanf("%d %d", &w, &c);
seq[w - 1].push_back(c);
}
for (int i = 0; i < Maxw; i++)
sort(seq[i].rbegin(), seq[i].rend());
ll cur = 0;
for (int i = 0; i < seq[2].size(); i++) {
cur += seq[2][i];
best[3 * (i + 1)] = cur;
}
for (int i = 0; i + 1 <= m; i++)
best[i + 1] = max(best[i + 1], best[i]);
printf("%I64d\n", Solve());
return 0;
}

Educational Codeforces Round 21E selling souvenirs (dp)的更多相关文章

  1. Educational Codeforces Round 63-D(基础DP)

    题目链接:https://codeforces.com/contest/1155/problem/D 题意:给定n个数,可以选择一段连续子段将其乘x,也可以不操作,求最大连续子段和. 思路:比赛时觉得 ...

  2. Educational Codeforces Round 62 E 局部dp + 定义状态取消后效性

    https://codeforces.com/contest/1140/problem/E 局部dp + 定义状态取消后效性 题意 给你一个某些位置可以改变的字符串,假如字符串存在回文子串,那么这个字 ...

  3. codeforces 808 E. Selling Souvenirs (dp+二分+思维)

    题目链接:http://codeforces.com/contest/808/problem/E 题意:最多有100000个物品最大能放下300000的背包,每个物品都有权值和重量,为能够带的最大权值 ...

  4. Educational Codeforces Round 52F(树形DP,VECTOR)

    #include<bits/stdc++.h>using namespace std;int n,k;vector<int>son[1000007];int dp[100000 ...

  5. [Educational Codeforces Round 63 ] D. Beautiful Array (思维+DP)

    Educational Codeforces Round 63 (Rated for Div. 2) D. Beautiful Array time limit per test 2 seconds ...

  6. Educational Codeforces Round 53 E. Segment Sum(数位DP)

    Educational Codeforces Round 53 E. Segment Sum 题意: 问[L,R]区间内有多少个数满足:其由不超过k种数字构成. 思路: 数位DP裸题,也比较好想.由于 ...

  7. Educational Codeforces Round 21

    Educational Codeforces Round 21  A. Lucky Year 个位数直接输出\(1\) 否则,假设\(n\)十进制最高位的值为\(s\),答案就是\(s-(n\mod ...

  8. [Educational Codeforces Round 16]E. Generate a String

    [Educational Codeforces Round 16]E. Generate a String 试题描述 zscoder wants to generate an input file f ...

  9. Educational Codeforces Round 37

    Educational Codeforces Round 37 这场有点炸,题目比较水,但只做了3题QAQ.还是实力不够啊! 写下题解算了--(写的比较粗糙,细节或者bug可以私聊2333) A. W ...

随机推荐

  1. java学习笔记(四)面向对象

    一.形參长度可变的方法 当传入被调用的函数參数数量不确定时,在方法最后一个形參的类型后加上三个点号(...),表明该形參能够接受多个參数值.多个參数值被当做数组传入,这些參数必须为指定的类型. pac ...

  2. Unity ----- 对象池GameObjectPool

    孙广东 2014.6.28 非常早之前看到的外国文章,认为不错,分享一下. 对象池在AssetStore中也是有非常多插件的,可是有些重了.自己写一个轻量的岂不是非常好. 当你须要创建大量某种类型对象 ...

  3. 嵌入式程序员应知道的0x10个C语言Tips

    [1].[代码] [C/C++]代码 跳至 [1] ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 ...

  4. Effective C++ 43,44

    43.明智地使用多继承. 多继承带来了极大的复杂性.最主要的一条就是二义性. 当派生类为多继承时,其多个基类有同名的成员时,就会出现二义性.通常要明白其使用哪个成员的.显式地限制修饰成员不仅非常笨拙, ...

  5. Mysql 数据库中间件

    读写分离:简单的说是把对数据库读和写的操作分开对应不同的数据库服务器,这样能有效地减轻数据库压力,也能减轻io压力.主数据库提供写操作,从数据库提供读操作,其实在很多系统中,主要是读的操作.当主数据库 ...

  6. 微软开源 Try .NET - 创建交互式.NET文档

    微软近日开源了一个新平台--Try .NET,该平台可以让开发者在线上编写并运行 .NET 代码.微软介绍,Try .NET 是一个可嵌入的代码运行器,不仅可以直接在线上对自己或者他人的代码进行编辑. ...

  7. (转)CSS3全局实现所有元素的内边距和边框不增加

    全局设置 border-box 很好,首先它符合直觉,其次它可以省去一次又一次的加加减减 它还有一个关键作用——让有边框的盒子正常使用百分比宽度.但是使用了 border-box 可能会与一些依赖默认 ...

  8. Drupal 7模板(主题钩子)的建议

    这一块的内容很多其它的讲的是样例.所以这里请直接稳步官方站点查看吧.链接 https://drupal.org/node/1089656

  9. MySQL 数据库 的安装和基本管理

    03-MySql安装和基本管理   本节掌握内容: mysql的安装.启动 mysql破解密码 统一字符编码 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Orac ...

  10. python的对象的属性(即对象的成员)是动态的

    1 python的对象的成员叫attribute 2 python的类的成员是可以动态创建的 因此,在用的时候也提供了三个内建的接口来对类的成员进行操作 2.1 getattr() 2.2 hasat ...