乍一看是01背包问题,wocao,太简单,这个我做过好多次,绝对没问题!第一次提交CE???What?怎么可能呢?好吧,数组开太大了,w在十亿内,数组开不了,那我数组开小一点吧,一亿,What?RE?这也不行,那也不行,看来这道题没这么简单。
又倒回去仔细读了一下题目,题目本身就是简单背包,一共才三句话,不可能理解错误,唯一的不同就是这道题的约束条件范围非常的大,然后突然发现:
For each i=2,3,...,N, w1≤wi≤w1+3.
这个条件在一般的背包问题里面好像没有,什么意思呢?对于2~i的每一个重量,它都在w1~w1+3这个重量范围之间,换句话说就是所有的w1只有四种可能,w1、w1+1、w1+2、w1+3,这个对于解题有什么作用呢?
#include
#include
#include
#define ll long long
#define MAXN 100000005
using namespace std;
//喜欢用结构体来存放每个物体的价值和重量,不太符合常规,哈哈哈
//等同于w[105],v[105]
struct TH{
ll w,v;
}th[105];
//按重量分四类用于存放价值的数组
ll v1[105],v2[105],v3[105],v4[105];
//每一类的数量
int cnt1=0,cnt2=0,cnt3=0,cnt4=0;
//后面要从大到小排序
bool cmp(ll a,ll b){
return a>b;
}
int main(){
ll n,w;
scanf("%lld %lld",&n,&w);
for(int i=1;i<=n;i++){
scanf("%lld %lld",&th[i].w,&th[i].v);
//第一个直接存到v1数组,从数组下标为1的地方开始存
if(i==1){
v1[++cnt1]=th[i].v;
continue;
}
//1开始分类咯,以w[1]为基准, 按重量把所有价值分为4类
int con=th[i].w-th[1].w;
switch(con){
case 0:v1[++cnt1]=th[i].v;break;
case 1:v2[++cnt2]=th[i].v;break;
case 2:v3[++cnt3]=th[i].v;break;
case 3:v4[++cnt4]=th[i].v;break;
}
}
//2每一类按价值价值从大到小排序
sort(v1+1,v1+cnt1+1,cmp);
sort(v2+1,v2+cnt2+1,cmp);
sort(v3+1,v3+cnt3+1,cmp);
sort(v4+1,v4+cnt4+1,cmp);
//3每种类型的物品价值叠加
for(int i=2;i<=cnt1;i++){
v1[i]+=v1[i-1];
}
for(int i=2;i<=cnt2;i++){
v2[i]+=v2[i-1];
}
for(int i=2;i<=cnt3;i++){
v3[i]+=v3[i-1];
}
for(int i=2;i<=cnt4;i++){
v4[i]+=v4[i-1];
}
//4准备完毕,可以开始找答案了
ll ans=0;
//每一类的枚举从0开始,v[0]肯定是0,因为我们的价值存放在1~cnt位嘛,所以不用担心影响结果
// 为什么必须从0开始?因为我可以选择这一类一个都不选啊
for(int i=0;i<=cnt1;i++){//枚举
for(int j=0;j<=cnt2;j++){
for(int k=0;k<=cnt3;k++){
for(int h=0;h<=cnt4;h++){
//枚举完数量就可以计算重量咯
if(th[1].w*(i)+(th[1].w+1)*(j)+(th[1].w+2)*(k)+(th[1].w+3)*(h)<=w){
//如果重量可以装下,就看总价值有没有更大咯
ans=max(ans,v1[i]+v2[j]+v3[k]+v4[h]);
}
}
}
}
}
printf("%lld",ans);
return 0;
}
找了一个别人的答案,看起来就要高级很多:
#include
//---------------------------
using namespace std;
//---------------------------
#define REP(i,n) for(int i = 0; i < (n); i++)
long long N,W,sm=0;
long long w[200];
long long v[200];
vector v1,v2,v3,v4;
int i,j,k,l,con;
int cnt[4];
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
cin >> N >> W;
REP(i,N){
cin >> w[i] >> v[i];
if(i == 0){
v1.push_back(v[i]);
}
if(i>=1){
con=w[i]-w[0];
if(con==0)v1.push_back(v[i]);
if(con==1)v2.push_back(v[i]);
if(con==2)v3.push_back(v[i]);
if(con==3)v4.push_back(v[i]);
}
}
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
sort(v3.begin(), v3.end());
sort(v4.begin(), v4.end());
reverse(v1.begin(), v1.end());
reverse(v2.begin(), v2.end());
reverse(v3.begin(), v3.end());
reverse(v4.begin(), v4.end());
for(i=0;i<(int)v1.size();i++){
if(i+1==(int)v1.size())continue;
v1[i+1]+=v1[i];
}
for(i=0;i<(int)v2.size();i++){
if(i+1==(int)v2.size())continue;
v2[i+1]+=v2[i];
}
for(i=0;i<(int)v3.size();i++){
if(i+1==(int)v3.size())continue;
v3[i+1]+=v3[i];
}
for(i=0;i<(int)v4.size();i++){
if(i+1==(int)v4.size())continue;
v4[i+1]+=v4[i];
}
v1.insert(v1.begin(), 0);
v2.insert(v2.begin(), 0);
v3.insert(v3.begin(), 0);
v4.insert(v4.begin(), 0);
REP(i, (int)v1.size()){
REP(j, (int)v2.size()){
REP(k, (int)v3.size()){
REP(l, (int)v4.size()){
if(i*w[0]+j*(w[0]+1)+k*(w[0]+2)+l*(w[0]+3) <= W){
sm = max(sm, v1[i]+v2[j]+v3[k]+v4[l]);
}
}
}
}
}
cout << sm << endl;
return 0;
}