题目链接:https://vjudge.net/contest/410631#problem/J
题意:给出n个物品和一个容量为W的包,随后n行给出每个物品的重量wi和价值vi,挑出价值小于等于W并且价值最大的物品,输出最大价值。
数据范围:n<=100,w<=1e9,v<=1e7,w1<=wi<=w1+3
思路:n的范围只有100,w的值只有四种,w1,w1+1,w1+2,w1+3,所以 n 3 n^3 n3枚举就可以,只要枚举w1,(w1+1),(w1+2)的个数,算出(w1+3)的个数,从大到小取就可以。
代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
typedef unsigned long long ull;
vector<int>G[5];
bool cmp(int a,int b){return a>b;}
int main(){
int n,W;scanf("%d%d",&n,&W);
int w1,x;scanf("%d%d",&w1,&x);
G[0].pb(x);
for(int i=1;i<n;i++)
{
int w,v;scanf("%d%d",&w,&v);
G[w-w1].pb(v);
}
ll ans=0;
for(int i=0;i<4;i++)sort(G[i].begin(),G[i].end(),cmp);
for(int i=0;i<=(int)G[0].size();i++)
for(int j=0;j<=(int)G[1].size();j++)
for(int k=0;k<=(int)G[2].size();k++)
{
ll sum=1ll*i*w1+1ll*j*(w1+1)+1ll*k*(w1+2);
if(sum>W)continue;
int tmp=(W-sum)/(w1+3);
ll res=0;
for(int p=0;p<i;p++)res+=G[0][p];
for(int p=0;p<j;p++)res+=G[1][p];
for(int p=0;p<k;p++)res+=G[2][p];
for(int p=0;p<min(tmp,(int)G[3].size());p++)res+=G[3][p];
ans=max(ans,res);
}
printf("%lld\n",ans);
return 0;
}