After several latest reforms many tourists are planning to visit Berland, and Berland people understood that it's an opportunity to earn money and changed their jobs to attract tourists. Petya, for example, left the IT corporation he had been working for and started to sell souvenirs at the market.

This morning, as usual, Petya will come to the market. Petya has n different souvenirs to sell; ith souvenir is characterised by its weight wi and cost ci. Petya knows that he might not be able to carry all the souvenirs to the market. So Petya wants to choose a subset of souvenirs such that its total weight is not greater than m, and total cost is maximum possible.

Help Petya to determine maximum possible total cost.

Input

The first line contains two integers n and m (1 ≤ n ≤ 100000, 1 ≤ m ≤ 300000) — the number of Petya's souvenirs and total weight that he can carry to the market.

Then n lines follow. ith line contains two integers wi and ci (1 ≤ wi ≤ 3, 1 ≤ ci ≤ 109) — the weight and the cost ofith souvenir.

Output

Print one number — maximum possible total cost of souvenirs that Petya can carry to the market.

Examples
input
1 1
2 1
output
0
input
2 2
1 3
2 2
output
3
input
4 3
3 10
2 7
2 8
1 1
output
10

  题目大意就是0-1背包问题,然后看着逆天的数据范围,O(nm)的算法怕是去卡评测机的。

  只能另想出路了。注意到每个物品的最大重量为3,突破口应该就在这儿。

  先按照物品的重量分类,排序(从大到小,因为同种重量选价值大不会更劣),求前缀和。

  考虑枚举重量为3的物品选择的物品的数量。考虑对剩下物品dp。不难证明容量+1后对策略的影响只有:

  • 加入一个重量为1的物品。
  • 拿走一个重量为1的物品加入一个重量为2的物品。

  (大概就是因为每次改变的物品重量和不会超过2,如果改变的物品重量和超过2,那么两边一定存在1个重量和为2的物品集合,把现在这个集合里的替换为新的集合中会更优,这样会矛盾)

  不过暴力记下每种重量的物品选择的数量也可以dp。讨论一下发现和这个操作是类似的。

  如果将两个物品拿来dp,然后最后枚举状态,计算第三种物品需要的量,再根据前缀和快速计算。如果用重量为1和2的物品来dp,经过一番考虑决定用f[i]表示当前总共装了质量为i的物品最大的价值和和两种物品各用的数量(对,没有看错,用的是一个结构体来存的)。

  为什么这么做是正确的?

  首先我们按照从大到小排序,如果说一个重量为2的物品比两个重量为1的物品优,那么对于这个状态以及这之前的状态,两个质量为1的物品都不会更优,并且会被这个重量为2的物品替换掉,也就是说最优的时候有确定的两种物品的数量,即使是两个重量为1的物品之和和一个重量为2的物品价值和相等,也不会影响。转移的时候我肯定希望能放的尽量大,所以转移的时候只需要枚举是装入下一个重量为1的物品还是重量为2的物品。

  最后计算一下答案,取max即可。

-->

Code

 /**
* Codeforces
* Problem#808E
* Accepted
* Time:31ms
* Memory:9400k
*/
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<vector>
#include<stack>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef bool boolean;
#define inf 0xfffffff
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b)
#define max3(a, b, c) max(a, max(b, c))
#define min3(a, b, c) min(a, min(b, c))
template<typename T>
inline boolean readInteger(T& u){
char x;
int aFlag = ;
while(!isdigit((x = getchar())) && x != '-' && x != -);
if(x == -) {
ungetc(x, stdin);
return false;
}
if(x == '-'){
x = getchar();
aFlag = -;
}
for(u = x - ''; isdigit((x = getchar())); u = (u << ) + (u << ) + x - '');
ungetc(x, stdin);
u *= aFlag;
return true;
} #define LL long long typedef class Data {
public:
LL val;
int s1, s2; Data():val(), s1(), s2() { }
}Data; int n, m;
Data* f;
int cnt[] = {, , , };
int vs[][];
LL s[][]; inline void init() {
readInteger(n);
readInteger(m);
f = new Data[(const int)(m + )];
for(int i = , v, w; i <= n; i++) {
readInteger(w);
readInteger(v);
vs[w][++cnt[w]] = v;
}
} boolean cmpare (const int& a, const int& b) {
return a > b;
} LL res = ; inline void solve() {
for(int i = ; i <= ; i++) {
sort(vs[i] + , vs[i] + cnt[i] + , cmpare);
s[i][] = ;
for(int j = ; j <= cnt[i]; j++)
s[i][j] = s[i][j - ] + vs[i][j];
} for(int i = ; i <= m; i++) {
if(f[i - ].s1 < cnt[] && f[i].val < f[i - ].val + vs[][f[i - ].s1 + ]) {
f[i].val = f[i - ].val + vs[][f[i - ].s1 + ];
f[i].s1 = f[i - ].s1 + , f[i].s2 = f[i - ].s2;
}
if(i >= && f[i - ].s2 < cnt[] && f[i].val < f[i - ].val + vs[][f[i - ].s2 + ]) {
f[i].val = f[i - ].val + vs[][f[i - ].s2 + ];
f[i].s2 = f[i - ].s2 + , f[i].s1 = f[i - ].s1;
}
} for(int i = ; i <= m; i++)
if((m - f[i].s1 - f[i].s2 * ) / <= cnt[])
smax(res, f[i].val + s[][(m - f[i].s1 - f[i].s2 * ) / ]);
else
smax(res, f[i].val + s[][cnt[]]);
printf(Auto, res);
} int main() {
init();
solve();
return ;
}

Educational Codeforces Round 21 Problem E(Codeforces 808E) - 动态规划 - 贪心的更多相关文章

  1. Educational Codeforces Round 21 Problem D(Codeforces 808D)

    Vasya has an array a consisting of positive integer numbers. Vasya wants to divide this array into t ...

  2. Educational Codeforces Round 21 Problem F (Codeforces 808F) - 最小割 - 二分答案

    Digital collectible card games have become very popular recently. So Vova decided to try one of thes ...

  3. Educational Codeforces Round 21 Problem A - C

    Problem A Lucky Year 题目传送门[here] 题目大意是说,只有一个数字非零的数是幸运的,给出一个数,求下一个幸运的数是多少. 这个幸运的数不是最高位的数字都是零,于是只跟最高位有 ...

  4. Educational Codeforces Round 21

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

  5. Educational Codeforces Round 32 Problem 888C - K-Dominant Character

    1) Link to the problem: http://codeforces.com/contest/888/problem/C 2) Description: You are given a ...

  6. Educational Codeforces Round 9 C. The Smallest String Concatenation —— 贪心 + 字符串

    题目链接:http://codeforces.com/problemset/problem/632/C C. The Smallest String Concatenation time limit ...

  7. Codeforces Round #524 (Div. 2) codeforces 1080A~1080F

    目录 codeforces1080A codeforces 1080B codeforces 1080C codeforces 1080D codeforces 1080E codeforces 10 ...

  8. Educational Codeforces Round 21 D.Array Division(二分)

    D. Array Division time limit per test:2 seconds memory limit per test:256 megabytes input:standard i ...

  9. Educational Codeforces Round 21(A.暴力,B.前缀和,C.贪心)

    A. Lucky Year time limit per test:1 second memory limit per test:256 megabytes input:standard input ...

随机推荐

  1. DDOS hulk,rudy

    HULK (HTTP Unbearable Load King) HULK HULK是另一个DOS攻击工具,这个工具使用UserAgent的伪造,来避免攻击检测,可以通过启动500线程对目标发起高频率 ...

  2. arcgis api for JavaScript _跨域请求

    arcgis api for JavaScript  中出现跨域请求是常见问题, 通常出现类似如下错误消息类似: XMLHttpRequest cannot load http://10.32.2.7 ...

  3. 【python-opencv】18-图像梯度+图像边界

    效果图: *一阶导数与Soble算子 *二阶导数与拉普拉斯算子 定义:把图片想象成连续函数,因为边缘部分的像素值是与旁边像素明显有区别的,所以对图片局部求极值,就可以得到整幅图片的边缘信息了. 不过图 ...

  4. extjs分页

    1.本地分页:设置store的proxy属性为pagingmemoryproxy实例 2.远程分页

  5. Python安装及运行中可能遇到的问题。

    1.报错找不到Selenium. 解决办法: (1)可以调整工具中的以下两项 Setting: (2)Setting中设置此目录为Python安装目录,选择设置中的第一项后配置以下Python3.5的 ...

  6. Spark Storage(二) 集群下的broadcast

    Broadcast 简单来说就是将数据从一个节点复制到其他各个节点,常见用于数据复制到节点本地用于计算,在前面一章中讨论过Storage模块中BlockManager,Block既可以保存在内存中,也 ...

  7. [py][mx]xadmin详细设置-将app注册到xadmin

    首先createsuperuser,创建用户, 然后登陆xadmin. 理解下models的各个字段 复数形式及返回 注册app users/adminx.py 显示字段 users/adminx.p ...

  8. RNN实现字符级语言模型 - 恐龙岛(自己写RNN前向后向版本+keras版本)

    问题描述:样本为所有恐龙名字,为了构建字符级语言模型来生成新的名称,你的模型将学习不同的名称模式,并随机生成新的名字. 在这里你将学习到: 如何存储文本数据以便使用rnn进行处理. 如何合成数据,通过 ...

  9. javascript按字节截取标题中字符串

    在网页展示中经常会碰到,标题过长,需要截取字符串,用CSS的实现的话各种兼容问题,下面为大家介绍下javascript如何按字节截取字符串 做为一个前端开发人员在网页展示中经常会碰到,标题过长,需要截 ...

  10. 9/24matplotlib使用入门

    ---恢复内容开始--- matplotlib的使用中有好几种输出风格,有matlab风格,和官方文档的as风格,各有所长,本文对比介绍官方文档中的使用风格. 我们画图的目的是要将函数以图像显示出来, ...