背包练习

1、采药(medic.pas/c/cpp)

【问题描述】

辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”

如果你是辰辰,你能完成这个任务吗?


【输入文件】

输入文件medic.in的第一行有两个整数T(1 <= T <= 1000)和M(1<= M <= 100),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。

 

【输出文件】

 

输出文件medic.out包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。

 

【样例输入】

 

70 3

71 100

69 1

1 2

 

【样例输出】

 

3

 

【数据规模】

 

对于30%的数据,M<= 10;

对于全部的数据,M <= 100。

 【思路】经典的01背包  这里给出滚动数组和一维优化两个版本

/*滚动数组*/ 
#include<cstdio>

int t,m,i,j;
int time[100],v[100];
int f[2][1001];

int main()
{
    freopen("medic.in","r",stdin);
    freopen("medic.out","w",stdout); 
    scanf("%d%d",&t,&m);
    for (i=0;i<m;i++) scanf("%d%d",&time[i],&v[i]);
    for (i=0;i<m;i++)
     {
       for (j=time[i];j<=t;j++)
         if (f[0][j-time[i]]+v[i]>f[1][j]) f[1][j]=f[0][j-time[i]]+v[i];
       for (j=0;j<=t;j++)  f[0][j]=f[1][j];    
       }
     printf("%d\n",f[0][t]);
     }  

/*一维*/ 
#include<cstdio>

int t,m,i,j;
int time[100],v[100];
int f[1001];

int main()
{
   freopen("medic.in","r",stdin);
    freopen("medic.out","w",stdout); 
    scanf("%d%d",&t,&m);
    for (i=0;i<m;i++) scanf("%d%d",&time[i],&v[i]);
    for (i=0;i<m;i++)
     {
       for (j=t;j>=time[i];j--)
        if (f[j-time[i]]+v[i]>f[j]) f[j]=f[j-time[i]]+v[i];
       }
     printf("%d",f[t]);
     }

2、装箱问题(30分)(box.pas)

问题描述

有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30=,每个物品有一个体积(正整数)。

要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

输入格式:一行数据,第一个整数,表示箱子容量,每二个整数,表示有n个物品,接下来n个数,分别表示这n 个物品的各自体积

输出格式:一个整数,表示箱子剩余空间。

样例

输入:(box.in)

24     6    8  3  12  7  9  7

输出:(box.out)

0  一个整数,表示箱子剩余空间。

【思路】01背包,把V[I]当成体积也当成价值

#include<cstdio>

int vm,n,i,j;
int v[30],f[20000];

int main(){
    freopen("box.in","r",stdin);
    freopen("box.out","w",stdout);
    scanf("%d%d",&vm,&n);
    for (i=0;i<n;i++) scanf("%d",&v[i]);
    for (i=0;i<n;i++)
      for (j=vm;j>=v[i];j--)
       if (f[j-v[i]]+v[i]>f[j]) f[j]=f[j-v[i]]+v[i];
    printf("%d\n",vm-f[vm]);
}      
    

3、背包问题(bag.pas)

设有n种物品,记作A1、A2、…、An,对应于每个Ai(1<=i<=n)都有一个重量Awi和价值Avi(重量和价值都为正整数)。另外,对应于每个Ai,都有一件可代替它的“代用品”Bi,Bi的重量和价值分别为Bwi和Bvi。本题的任务是:选择这n件物品或其代用品的一个子集装进背包,使总重量不超过给定重量TOT,同时使总价值VAL最高。装填的第i步,要么装入Ai,要么装入Bi,要么Ai和Bi都不装。

 

输入数据:

从文件中读取,文件的格式如下:

第一行:n  TOT   (n<1000,tot<100000)

第二行:Aw1  Av1  Bw1 Bv1

第三行:Aw2  Av2  Bw2 Bv2

            ……

第n+1行:Awn  Avn  BWn  BVn

 

输出数据:

    输出入文件中只有一个数值VAL

 

例如:

input.txt

2 10 

   3 6 2 3

6 9 5 10

 

output.txt

16

 

【思路】01背包加强版,不同的是要多加一重判断,装A[I]较优还是B[I]较优

              注意要用临时变量来更新F[I]的最优值,不然会出现装了A[I]又装B[I] (体积相等时)

              体积有可能为0

#include<cstdio>

long n,tot,i,j;
long awi[1000],avi[1000],bwi[1000],bvi[1000],f[100000];


long Min(long a,long b) 
{
      if (a>b) return b; 
      return a;
      }

int main(){
    freopen("bag.in","r",stdin);
    freopen("bag.out","w",stdout);
    scanf("%ld%ld",&n,&tot);
    for (i=0;i<n;i++) scanf("%ld%ld%ld%ld",&awi[i],&avi[i],&bwi[i],&bvi[i]);
    for (i=0;i<n;i++)
      for (j=tot;j>=0;j--){  //j=0
        long max=f[j];
        if (j>=awi[i] && f[j-awi[i]]+avi[i]>max) max=f[j-awi[i]]+avi[i];//f[j]=f[j-awi[i]]+avi[i];
        if (j>=bwi[i] && f[j-bwi[i]]+bvi[i]>max) max=f[j-bwi[i]]+bvi[i];// f[j]=f[j-bwi[i]]+bvi[i];
        f[j]=max;
        }
     printf("%ld\n",f[tot]);
     }   


4、开心的金明

(happy.pas/c/cpp)

【问题描述】

金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”。今天一早金明就开始做预算,但是他想买的东西太多了,肯定

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值