codeforces 808e

来源:互联网 发布:2016淘宝c店越来越难做 编辑:程序博客网 时间:2024/04/30 17:53

题目:http://codeforces.com/contest/808/problem/E

题目大意:
有n个物品,背包容量为m。
每个物品只会有1,2,3个单位占有空间,价值为c。
现在问如何可以使拿到的物品的价值最大。

思路:
看似一个简单01背包。。结果n=100000,m=300000。。
暴力dp直接tle。

主要就是只有三种单位。这就简单了。
贪心的思想,在相同的占有空间的时候,一定选价值最大的。
所以给物品排一个序。
dp第1,2种单位的占有空间,每次可以通过dp[i - 1].s1和dp[i - 2].s2来知道当前已经用到了第多少个第1,2种单位的物品。
然后所有都dp完之后,第三种物品尽可能的选,看看什么情况价值最大就可以了。

/*@resources: codeforces 808e@date: 2017-5-17@author: QuanQqqqq@algorihtm: dp*/#include <bits/stdc++.h>#define ll long long#define MAXN 300005using namespace std;struct node{    ll v,s1,s2;}dp[MAXN];ll goods[4][MAXN];ll num[4];ll sum[MAXN];int cmp(ll a,ll b){    return a > b;}int main(){    ll n,m,w,c;    while(~scanf("%lld %lld",&n,&m)){        memset(goods,0,sizeof(goods));        memset(num,0,sizeof(num));        memset(dp,0,sizeof(dp));        for(ll i = 0;i < n;i++){            scanf("%lld %lld",&w,&c);            goods[w][++num[w]] = c;        }        for(ll i = 1;i <= 3;i++){            sort(goods[i] + 1,goods[i] + 1 + num[i],cmp);        }        for(ll i = 1;i <= num[3];i++){            sum[i] = sum[i - 1] + goods[3][i];        }        for(ll i = 1;i <= m;i++){            dp[i] = dp[i - 1];            if(dp[i - 1].v + goods[1][dp[i - 1].s1 + 1] > dp[i].v){                dp[i].v = dp[i - 1].v + goods[1][dp[i - 1].s1 + 1];                dp[i].s1 = dp[i - 1].s1 + 1;                dp[i].s2 = dp[i - 1].s2;            }            if(i >= 2 && dp[i - 2].v + goods[2][dp[i - 2].s2 + 1] > dp[i].v){                dp[i].v = dp[i - 2].v + goods[2][dp[i - 2].s2 + 1];                dp[i].s1 = dp[i - 2].s1;                dp[i].s2 = dp[i - 2].s2 + 1;            }        }        ll ans = 0;        for(ll i = 0;i <= num[3] && i * 3 <= m;i++){            ans = max(ans,dp[m - i * 3].v + sum[i]);        }        printf("%lld\n",ans);    }}
原创粉丝点击