CSU 1097 Gifts with different style

来源:互联网 发布:matlab未知数矩阵 编辑:程序博客网 时间:2024/06/06 07:11

1097: Gifts with different style

Time Limit: 1 Sec  Memory Limit: 16 MB
SUBMIT: 139  Solved: 38
[SUBMIT][STATUS]

Description

    前些日子GBQC国的小明在凤凰古城痛痛快快地玩了两天,临走之前希望给女友带回两件不同种类的纪念品,而且小明的背包最多只能容纳总体积不超过V的物品,各个纪念品使其女友的高兴程度的增加值也不全是一样的。

    现在小明想知道,对于小明有有财力购买的N个纪念品,他需要买回哪两个才能使女友的高兴程度的增加值最大呢?

Input

输入包含多组测试数据。

对于每组测试数据,第一行包含三个整数N(1<=N<=10^5), C(1<=C<=10^4), V(1<=V<=10^4),其中N表示小明有财力购买的一共有N个纪念品,C表示市面上销售的纪念品一共可以分为C个种类,V表示小明的背包最多只能容纳体积不超过V的物品。接下来N行,每行用三个正整数i(1<=i<=C)、j(1<=j<=10^4)、k(1<=k<=10^5)描述一个可以购买的纪念品,表示这个纪念品属于第i个种类,其体积为j,如果将其买回可使女友的高兴程度增加k。

Output

对于每组测试数据,用一行输出一个整数表示小明最多可以让女友的高兴程度增加多少。如果小明没办法带回两件不同种类的纪念品,则输出“-1”(不包括引号)。

Sample Input

2 3 51 2 32 4 13 3 51 2 41 2 53 3 2

Sample Output

-17

HINT

    由于数据量较大,推荐使用scanf和printf。



Source

CSU Monthly 2012 Aug.


这个题目咋一看,还以为是个分组背包问题(据说分组背包优化一下可以水过),不过正解是线段树

题目的关键之处在于只取2件物品,用线段树保存前k类,在1-v体积下的最大价值。然后计算在前k类和k+1类中各取一个的最大价值。

线段树还是有些不熟0.0

另外原来scanfprintfcincout快很多 Orz.......

我开始还以为是一样的呢,以后尽量用scanfprintf

Num[rt]保存的是在区域类的最大值.


#include<stdio.h>#include<vector>using namespace std; #define MAXN 10001#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define max(a,b) a>b?a:bstruct node{    int w,v;}; int num[MAXN<<2]; void build(int l,int r,int rt){    num[rt]=0;    if(l==r)        return ;    int m=(l+r)>>1;    build(lson);    build(rson);} void update(int w,int v,int l,int r,int rt){    num[rt]=max(v,num[rt]);    if(l==r)        return ;    int m=(l+r)>>1;    if(w<=m)        update(w,v,lson);    else        update(w,v,rson);} int query(int tmp,int l,int r,int rt){    if(l==r)        return num[rt];    int m=(l+r)>>1;    if(tmp<=m)        return query(tmp,lson);    else        return max(num[rt<<1],query(tmp,rson));} int main(void){    int N,C,V;    freopen("d:\\in.txt","r",stdin);    while(scanf("%d%d%d",&N,&C,&V)==3)    {        vector<node>list[10001];        node tmp;        int i,j,k;        for(i=1;i<=N;i++)        {            scanf("%d%d%d",&k,&tmp.w,&tmp.v);            list[k].push_back(tmp);        }        build(1,V,1);        int len,temp;        int sum=-1;        for(i=1;i<=C;i++)        {            len=list[i].size();            if(!len)                continue;            for(j=0;j<len;j++)                            if(V-list[i][j].w>0)                {                    temp=query(V-list[i][j].w,1,V,1);   //前k类在V-list[i][j].w下的最大值                    if(temp)                        sum=max(sum,temp+list[i][j].v);                }            for(j=0;j<len;j++)            //更新前k类在各种容量下的最大值                if(list[i][j].w<=V)                    update(list[i][j].w,list[i][j].v,1,V,1);        }        printf("%d\n",sum);    }    return 0;}




原创粉丝点击