AtCoder Regular Contest 073 D - Simple Knapsack(贪心)

Time limit : 2sec / Memory limit : 256MB

Score : 400 points

Problem Statement

You have N items and a bag of strength W. The i-th item has a weight of wi and a value of vi.

You will select some of the items and put them in the bag. Here, the total weight of the selected items needs to be at most W.

Your objective is to maximize the total value of the selected items.

Constraints

  • 1N100
  • 1W109
  • 1wi109
  • For each i=2,3,…,Nw1wiw1+3.
  • 1vi107
  • W, each wi and vi are integers.

Input

Input is given from Standard Input in the following format:

N W
w1 v1
w2 v2
:
wN vN

Output

Print the maximum possible total value of the selected items.


Sample Input 1

Copy
4 6
2 1
3 4
4 10
3 4

Sample Output 1

Copy
11

The first and third items should be selected.


Sample Input 2

Copy
4 6
2 1
3 7
4 10
3 6

Sample Output 2

Copy
13

The second and fourth items should be selected.


Sample Input 3

Copy
4 10
1 100
1 100
1 100
1 100

Sample Output 3

Copy
400

You can take everything.


Sample Input 4

Copy
4 1
10 100
10 100
10 100
10 100

Sample Output 4

Copy
0

You can take nothing.

题意是给你n个物品,你有一个容量为w的背包,每一个物品都有它的重量和价值,让你从n个中选取若干个,使得总重量不超过背包的上限,而且使得价值最大,会发现这和01背包是一样的,然而背包的复杂度是O(nw),这里的数据范围不允许这么搞。

仔细观察会发现,物品只有4种重量,物品的总数最多只有100,所以我们可以把物品分成4种,然后从大到小排序,枚举每一种的数量,这样就可以求出最大的价值。

(我的写法可能很挫。。。但是一时没想到有优美的写法)


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;

struct good
{
    int w,v;
}g[110];

bool cmp(good a,good b)
{
    return a.v > b.v;
}
good A[110],B[110],C[110],D[110];

LL swa[110],swb[110],swc[110],swd[110];//重量的前缀和
LL sva[110],svb[110],svc[110],svd[110];//价值的前缀和

int main(void)
{
    int n,w,i,j,k,l;
    int a,b,c,d;
    while(scanf("%d%d",&n,&w)==2)
    {
        a = b = c = d = 0;
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&g[i].w,&g[i].v);
            if(g[i].w == g[1].w)
                A[++a] = g[i];
            if(g[i].w == g[1].w + 1)
                B[++b] = g[i];
            if(g[i].w == g[1].w + 2)
                C[++c] = g[i];
            if(g[i].w == g[1].w + 3)
                D[++d] = g[i];
        }
        sort(A+1,A+a+1,cmp);
        sort(B+1,B+b+1,cmp);
        sort(C+1,C+c+1,cmp);
        sort(D+1,D+d+1,cmp);
        swa[0] = swb[0] = swc[0] = swd[0] = 0;
        sva[0] = svb[0] = svc[0] = svd[0] = 0;
        for(i=1;i<=a;i++)
        {
            swa[i] = swa[i-1] + A[i].w;
            sva[i] = sva[i-1] + A[i].v;
        }
        for(i=1;i<=b;i++)
        {
            swb[i] = swb[i-1] + B[i].w;
            svb[i] = svb[i-1] + B[i].v;
        }
        for(i=1;i<=c;i++)
        {
            swc[i] = swc[i-1] + C[i].w;
            svc[i] = svc[i-1] + C[i].v;
        }
        for(i=1;i<=d;i++)
        {
            swd[i] = swd[i-1] + D[i].w;
            svd[i] = svd[i-1] + D[i].v;
        }
        int sumv = 0;
        int ans = 0;
        for(i=0;i<=a;i++)
        {
            for(j=0;j<=b;j++)
            {
                for(k=0;k<=c;k++)
                {
                    for(l=0;l<=d;l++)
                    {
                        LL sum = swa[i] + swb[j] + swc[k] + swd[l];
                        if(sum <= (LL)w)
                        {
                            ans = max((LL)ans,sva[i]+svb[j]+svc[k]+svd[l]);
                        }
                    }
                }
            }
        }
        cout << ans << endl;
    }

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值