背包问题3

1272:【例9.16】分组背包

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 3443 通过数: 2163

【题目描述】
一个旅行者有一个最多能装V公斤的背包,现在有n件物品,它们的重量分别是W1,W2,…,WnW1,W2,…,Wn,它们的价值分别为C1,C2,…,CnC1,C2,…,Cn。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

【输入】
第一行:三个整数,V(背包容量,V≤200),N(物品数量,N≤30)和T(最大组号,T≤10);

第2…N+1行:每行三个整数Wi,Ci,PWi,Ci,P,表示每个物品的重量,价值,所属组号。

【输出】
仅一行,一个数,表示最大总价值。

【输入样例】
10 6 3
2 1 1
3 3 1
4 8 2
6 9 2
2 8 3
3 9 3
【输出样例】
20


#include <iostream>
using namespace std;
int a[15][35];
int f[205];
int main()
{
    int v,n,t;
    cin>>v>>n>>t;
    int w[35],c[35];
    int p;
    for(int i=1;i<=n;i++)
    {
        cin>>w[i]>>c[i]>>p;
        a[p][++a[p][0]]=i;
    }
    for(int i=1;i<=t;i++)
        for(int j=v;j>=0;j--)
        for(int k=1;k<=a[i][0];k++)
    {
        if(j>=w[a[i][k]])
        {
            int z=w[a[i][k]];
            f[j]=max(f[j],f[j-z]+c[a[i][k]]);
        }
    }
    cout<<f[v]<<endl;
    return 0;
}

 

其他背包问题
1271:【例9.15】潜水员

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 4319 通过数: 2493

【题目描述】
潜水员为了潜水要使用特殊的装备。他有一个带2种气体的气缸:一个为氧气,一个为氮气。让潜水员下潜的深度需要各种的数量的氧和氮。潜水员有一定数量的气缸。每个气缸都有重量和气体容量。潜水员为了完成他的工作需要特定数量的氧和氮。他完成工作所需气缸的总重的最低限度的是多少?

例如:潜水员有5个气缸。每行三个数字为:氧,氮的(升)量和气缸的重量:

3 36 120

10 25 129

5 50 250

1 45 130

4 20 119

如果潜水员需要5升的氧和60升的氮则总重最小为249(1,2或者4,5号气缸)。

你的任务就是计算潜水员为了完成他的工作需要的气缸的重量的最低值。

【输入】
第一行有2整数m,n(1≤m≤21,1≤n≤79)。它们表示氧,氮各自需要的量。

第二行为整数k(1≤n≤1000)表示气缸的个数。

此后的k行,每行包括ai,bi,ci(1≤ai≤21,1≤bi≤79,1≤ci≤800)3ai,bi,ci(1≤ai≤21,1≤bi≤79,1≤ci≤800)3整数。这些各自是:第i个气缸里的氧和氮的容量及汽缸重量。

【输出】
仅一行包含一个整数,为潜水员完成工作所需的气缸的重量总和的最低值。

【输入样例】
5 60
5
3 36 120
10 25 129
5 50 250
1 45 130
4 20 119【输出样例】
249
很明显需要两个条件,但这道题的意思是容量能多不能少,因而往常一贯的减号要改成加号。而且要确保从零开始加,只用从零开始加的情况,那么初始化时只有F(0)(0)为零,其余为极大值。

#include <iostream>
#include<cstring>
using namespace std;
int main()
{
    int f[100][100];
    int m,n;
    int k;
    cin>>m>>n>>k;
    int a[1001],b[1001],c[1001];
    for(int i=1;i<=k;i++)
        cin>>a[i]>>b[i]>>c[i];
        memset(f,127,sizeof(f));
        f[0][0]=0;
    for(int i=1;i<=k;i++)
        for(int j=m;j>=0;j--)
        for(int l=n;l>=0;l--)
    {
        int t1,t2;
        t1=j+a[i];
        t2=l+b[i];
        if(t1>m)t1=m;
        if(t2>n)t2=n;
        f[t1][t2]=min(f[t1][t2],f[j][l]+c[i]);
    }
    cout<<f[m][n]<<endl;
    return 0;
}

1292:宠物小精灵之收服

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 2898 通过数: 1761

【题目描述】
宠物小精灵是一部讲述小智和他的搭档皮卡丘一起冒险的故事。

一天,小智和皮卡丘来到了小精灵狩猎场,里面有很多珍贵的野生宠物小精灵。小智也想收服其中的一些小精灵。然而,野生的小精灵并不那么容易被收服。对于每一个野生小精灵而言,小智可能需要使用很多个精灵球才能收服它,而在收服过程中,野生小精灵也会对皮卡丘造成一定的伤害(从而减少皮卡丘的体力)。当皮卡丘的体力小于等于0时,小智就必须结束狩猎(因为他需要给皮卡丘疗伤),而使得皮卡丘体力小于等于0的野生小精灵也不会被小智收服。当小智的精灵球用完时,狩猎也宣告结束。

我们假设小智遇到野生小精灵时有两个选择:收服它,或者离开它。如果小智选择了收服,那么一定会扔出能够收服该小精灵的精灵球,而皮卡丘也一定会受到相应的伤害;如果选择离开它,那么小智不会损失精灵球,皮卡丘也不会损失体力。

小智的目标有两个:主要目标是收服尽可能多的野生小精灵;如果可以收服的小精灵数量一样,小智希望皮卡丘受到的伤害越小(剩余体力越大),因为他们还要继续冒险。

现在已知小智的精灵球数量和皮卡丘的初始体力,已知每一个小精灵需要的用于收服的精灵球数目和它在被收服过程中会对皮卡丘造成的伤害数目。请问,小智该如何选择收服哪些小精灵以达到他的目标呢?

【输入】
输入数据的第一行包含三个整数:N(0<N<1000),M(0<M<500),K(0<K<100),分别代表小智的精灵球数量、皮卡丘初始的体力值、野生小精灵的数量。

之后的K行,每一行代表一个野生小精灵,包括两个整数:收服该小精灵需要的精灵球的数量,以及收服过程中对皮卡丘造成的伤害。

【输出】
输出为一行,包含两个整数:C,R,分别表示最多收服C个小精灵,以及收服C个小精灵时皮卡丘的剩余体力值最多为R。

【输入样例】
10 100 5
7 10
2 40
2 50
1 20
4 20【输出样例】
3 30
需要两个条件那就用两个二维数组分别表示。


#include <iostream>
using namespace std;
int a[105],b[105];
int f[1001][505];
int h[1001][505];
int main()
{
    int n,m,k;
    cin>>n>>m>>k;
    for(int i=1;i<=k;i++)
    {
        cin>>a[i]>>b[i];
    }
    for(int i=1;i<=k;i++)
        for(int j=n;j>=a[i];j--)
        for(int l=m;l>=b[i];l--)
    {
        if(f[j][l]<f[j-a[i]][l-b[i]]+1)
        {
        f[j][l]=f[j-a[i]][l-b[i]]+1;
        h[j][l]=h[j-a[i]][l-b[i]]+b[i];
        }
        else if(f[j][l]==f[j-a[i]][l-b[i]]+1&&h[j][l]>h[j-a[i]][l-b[i]]+b[i])
        {
            h[j][l]=h[j-a[i]][l-b[i]]+b[i];
        }
    }
    cout<<f[n][m]<<" "<<m-h[n][m]<<endl;
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值