题目连链接:
1279: 简单的背包问题
时间限制: 1 秒 内存限制: 32 MB
提交: 411 解决: 36
提交 状态
题目描述
相信大家都学过背包问题了吧,那么现在我就考大家一个问题。有n个物品,每个物品有它的重量w,价值v,现在有一个容量为W的背包,问你在不超过背包容量的情况下,能装下的物品的最大价值是多少。
T <= 100代表样例数
1 <= n <= 100 物品数
1 <= W <= 100000 背包的容量
1 <= wi <= 100000 每个物品的重量
对于每个i=2,3,…,N, w1 ≤ wi ≤ w1+3.
1 <= vi <= 100000 每个物品的价值
输入
输入格式:
T
n W
w1 v1
w2 v2
:
wn vn
输出
输出占一行,代表最大能装下物品的价值。
样例输入
2
4 6
2 1
3 4
4 10
3 4
4 6
2 1
3 7
4 10
3 6
样例输出
11
13
分析:一开始我看错了没有注意数据范围,一上去就把背包问题写了上去,一直wa了十几次,浪费了大量时间。赛后看题解才知道,重量有限制,只能在w1,w1+1,w1+2,w1+3,这四个范围之内。可以先给这个个分组,每一组按价值从大到小排,对于每组优先装入价值最大的。求个前缀和,四个for求最值就可以了,就是个贪心,被这个背包问题的题目迷惑了。
ac代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
int cmp(ll a,ll b){
return a>b;
}
int main(void){
int t;
cin>>t;
while(t--){
ll d[4][105];
ll n,W;
ll w1;
cin>>n>>W;
int a,b,c,d1;
a = b = c = d1 = 0;
cin>>w1>>d[0][++a];
for(int i=1;i<n;i++){
int xx,yy;
cin>>xx>>yy;
if(xx==w1){
d[0][++a] = yy;
}
else if(xx==w1+1){
d[1][++b] = yy;
}
else if(xx==w1+2){
d[2][++c] = yy;
}
else{
d[3][++d1] = yy;
}
}
sort(d[0]+1,d[0]+a+1,cmp);
sort(d[1]+1,d[1]+b+1,cmp);
sort(d[2]+1,d[2]+c+1,cmp);
sort(d[3]+1,d[3]+d1+1,cmp);
d[0][0] = d[1][0] =d[2][0] =d[3][0] = 0;
for(int i =2;i<=a;i++){
d[0][i]+=d[0][i-1];
}
for(int i=2;i<=b;i++){
d[1][i]+=d[1][i-1];
}
for(int i=2;i<=c;i++){
d[2][i]+=d[2][i-1];
}
for(int i=2;i<=d1;i++){
d[3][i]+=d[3][i-1];
}
ll res = 0;
for(int i=0;i<=a;i++){
for(int j=0;j<=b;j++){
for(int k=0;k<=c;k++){
for(int l=0;l<=d1;l++){
ll sum = w1*i+(w1+1)*j+(w1+2)*k+(w1+3)*l;
if(sum<=W){
res = max(res,d[0][i]+d[1][j]+d[2][k]+d[3][l]);
}
}
}
}
}
cout<<res<<endl;
}
return 0;
}
/**************************************************************
Problem: 1279
User: henuwhr
Language: C++
Result: 正确
Time:460 ms
Memory:1704 kb
****************************************************************/