您的位置:首页 > Web前端

CSU 1097 Gifts with different style

2012-10-03 21:12 429 查看

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

另外原来scanf和printf比cin和cout快很多 Orz.......

我开始还以为是一样的呢,以后尽量用scanf和printf了

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:b
struct 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐