珍惜现在,感恩生活(多重背包)

悼念512汶川大地震遇难同胞——珍惜现在,感恩生活

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 17114    Accepted Submission(s): 7227


Problem Description
急!灾区的食物依然短缺!
为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买。
请问:你用有限的资金最多能采购多少公斤粮食呢?

后记:
人生是一个充满了变数的生命过程,天灾、人祸、病痛是我们生命历程中不可预知的威胁。
月有阴晴圆缺,人有旦夕祸福,未来对于我们而言是一个未知数。那么,我们要做的就应该是珍惜现在,感恩生活——
感谢父母,他们给予我们生命,抚养我们成人;
感谢老师,他们授给我们知识,教我们做人
感谢朋友,他们让我们感受到世界的温暖;
感谢对手,他们令我们不断进取、努力。
同样,我们也要感谢痛苦与艰辛带给我们的财富~


 


Input
输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。
 


Output
对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。
 


Sample Input
  
  
1 8 2 2 100 4 4 100 2
 


Sample Output
  
  
400
 


Author
lcy
 

#include<stdio.h> 
#include<string.h> 
int dp[102]; 
int p[102],h[102],c[102]; 
int n,m; 
void comback(int v,int w)//经费,重量。完全背包; 

    for(int i=v; i<=n; i++) 
        if(dp[i]<dp[i-v]+w) 
            dp[i]=dp[i-v]+w; 

void oneback(int v,int w)//经费,重量;01背包; 

    for(int i=n; i>=v; i--) 
        if(dp[i]<dp[i-v]+w) 
            dp[i]=dp[i-v]+w; 

int main() 

    int ncase,i,j,k; 
    scanf("%d",&ncase); 
    while(ncase--) 
    { 
        memset(dp,0,sizeof(dp)); 
        scanf("%d%d",&n,&m);//经费,种类; 
        for(i=1; i<=m; i++) 
        { 
            scanf("%d%d%d",&p[i],&h[i],&c[i]);//价值,重量,数量; 
            if(p[i]*c[i]>=n) comback(p[i],h[i]); 
            else 
            { 
                for(j=1; j<c[i]; j<<1) 
                { 
                    oneback(j*p[i],j*h[i]); 
                    c[i]=c[i]-j; 
                } 
                oneback(p[i]*c[i],h[i]*c[i]); 
            } 
        } 
        printf("%d\n",dp[n]); 
    } 
    return 0; 


01背包优化:


#include <iostream> 
#include<cstring>
using namespace std; 
int main() 

    int nCase,Limit,nKind,i,j,k,  v[111],w[111],c[111],dp[111]; 
    //v[]存价值,w[]存尺寸,c[]存件数 
    //在本题中,价值是米的重量,尺寸是米的价格 
    int count,Value[1111],size[1111]; 
    //count存储分解完后的物品总数 
    //Value存储分解完后每件物品的价值 
    //size存储分解完后每件物品的尺寸 
    cin>>nCase; 
    while(nCase--) 
    { 
        count=0; 
        cin>>Limit>>nKind; 
        for(i=0; i<nKind; i++) 
        { 
            cin>>w[i]>>v[i]>>c[i]; 
            //对该种类的c[i]件物品进行二进制分解 
            for(j=1; j<=c[i]; j<<=1) 
            { 
                //<<右移1位,相当于乘2 
                Value[count]=j*v[i]; 
                size[count++]=j*w[i]; 
                c[i]-=j; 
            } 
            if(c[i]>0) 
            { 
                Value[count]=c[i]*v[i]; 
                size[count++]=c[i]*w[i]; 
            } 
        } 
        //经过上面对每一种物品的分解, 
        //现在Value[]存的就是分解后的物品价值 
        //size[]存的就是分解后的物品尺寸 
        //count就相当于原来的n 
        //下面就直接用01背包算法来解 
        memset(dp,0,sizeof(dp)); 
        for(i=0; i<count; i++) 
            for(j=Limit; j>=size[i]; j--) 
                if(dp[j]<dp[j-size[i]]+Value[i]) 
                    dp[j]=dp[j-size[i]]+Value[i]; 
 
        cout<<dp[Limit]<<endl; 
    } 
    return 0; 







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值