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
#include
#include
#include
#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;
}


你可能感兴趣的:(AtCoder Regular Contest 073 D - Simple Knapsack(贪心))