2-E

题目链接:https://vjudge.net/contest/208482#problem/E

题目大意n个物品,有一个容量为w的背包,每一个物品都有它的重量和价值,从n个中选取若干个,使得总重量不超过背包的上限,而且使得价值最大。

数据范围

1N100

1W109

1wi109

For each i=2,3,…,Nw1wiw1+3.

1vi107

W, each wi and vi are integers.
 

解题思路第一反应,这是01背包,but背包的复杂度是O(nw),所以,第一次超时了。

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

超时代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
long long n,m,w[110],v[110],f[10000000];

double s1,s2,s;
int main()
{
	cin>>n>>m;
	for(int i=1;i<n;i++)
	cin>>w[i]>>v[i];
	
	for(int i=1;i<=n;i++)
	for(int j=m;j>=w[i];j--)
	f[j]=max(f[j],f[j-w[i]]+v[i]);
	cout<<f[m];
	return 0;
} 
AC代码:
#include<iostream>  
#include<algorithm> 
#include<cstdio>  
#include<cstring>    
using namespace std;  
int n,m,a,b,c,d;
long long sum,ans; 
struct node  
{  
    int w,v;  
}g[110];  
  
bool cmp(node a,node b)  
{  
    return a.v>b.v;  
}  
node A[110],B[110],C[110],D[110];  
  
long long swa[110],swb[110],swc[110],swd[110];  
long long sva[110],svb[110],svc[110],svd[110]; 
  
int main()  
{  
        cin>>n>>m; 
        for(int i=1;i<=n;i++)  
        {  
            cin>>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);  
        
        for(int i=1;i<=a;i++)  
        {  
            swa[i]=swa[i-1]+A[i].w;  
            sva[i]=sva[i-1]+A[i].v;  
        }  
        for(int i=1;i<=b;i++)  
        {  
            swb[i]=swb[i-1]+B[i].w;  
            svb[i]=svb[i-1]+B[i].v;  
        }  
        for(int i=1;i<=c;i++)  
        {  
            swc[i]=swc[i-1]+C[i].w;  
            svc[i]=svc[i-1]+C[i].v;  
        }  
        for(int i=1;i<=d;i++)  
        {  
            swd[i]=swd[i-1]+D[i].w;  
            svd[i]=svd[i-1]+D[i].v;  
        }  
    
        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<=d;l++)  
        {  
        sum=swa[i]+swb[j]+swc[k]+swd[l];  
        if(sum<=m)  
        ans=max(ans,sva[i]+svb[j]+svc[k]+svd[l]);  
              
        }  
        cout<<ans<<endl;  
    
  
    return 0;  
}  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值