分组背包

本文深入探讨了两种背包问题:一种是每种品牌至少购买一双鞋,求最大价值;另一种是在有限时间内选择课程,每天只能上一课,求最大收益。通过具体代码实现,详细解释了动态规划在解决这些问题中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

I love sneakers!

题意:(至少选一个)

有n种品牌的鞋子,m元钱,k种鞋子

每种鞋子有三种属性:品牌,价值,价格

每种品牌至少买一双,问用m元最多买多少价值的鞋子?

解析:

这题和普通的分组背包不同,这里每种至少一个,可以多选

定义状态dp[i][v]表示买了i种物品,用来v钱,收获的最大价值

每个牌子至少买一双,这个可以用初始化dp[i][j]=-inf,dp[0]=0,来处理

dp[1][j]一定是从dp[0]转化来打,以此类推,知道dp[k]

转移方程:

dp[i][v]=max(dp[i][v],dp[i][v-vc[i][j].p]+vc[i][j].v);//注意顺序
dp[i][v]=max(dp[i][v],dp[i-1][v-vc[i][j].p]+vc[i][j].v);

这里要注意这两个方程的顺序,因为vc[i][j].p可能==0,所以如果顺序反了,一件物品可能买了两次

ac:

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
#define MAXN 10005
using namespace std;
struct node
{
    int v,p;
};
vector<node> vc[11];
ll dp[11][MAXN];

int main()
{
    int n,m,k,a,b,c;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        for(int i=0;i<=k;i++)
            vc[i].clear();
        for(int i=0;i<n;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            vc[a].push_back({c,b});
        }
        memset(dp,-inf,sizeof(dp));
        memset(dp[0],0,sizeof(dp[0]));
        for(int i=1;i<=k;i++)
        {
            int len=vc[i].size();
            for(int j=0;j<len;j++)
            {
                for(int v=m;v>=vc[i][j].p;v--)
                {
                    dp[i][v]=max(dp[i][v],dp[i][v-vc[i][j].p]+vc[i][j].v);//注意顺序
                    dp[i][v]=max(dp[i][v],dp[i-1][v-vc[i][j].p]+vc[i][j].v);
                }
            }
        }
        if(dp[k][m]<0)
            printf("Impossible\n");
        else
            printf("%lld\n",dp[k][m]);
    }
    return 0;
}

题意:(至多选一个)

给一个矩阵a[][]

a[i][j]表示用j天学习第i个课程能够得到A[i][j]的收益

求m天内获得的收益最大值,一天只能上一节课

ac:

#include<bits/stdc++.h>
#define MAXN 105
using namespace std;
int dp[MAXN],a[MAXN][MAXN];

int main()//分组背包
{
    int n,m,i,j,k;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)
            break;
        memset(dp,0,sizeof(dp));
        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)
            {
                scanf("%d",&a[i][j]);
            }
        }
        for(i=0;i<n;i++)//这三个循环的顺序决定了不会取同一组的物品
        {
            for(j=m;j>=0;j--)
            {
                for(k=0;k<j;k++)
                {
                    dp[j]=max(dp[j],dp[j-k-1]+a[i][k]);
                }
            }
        }
        printf("%d\n",dp[m]);
    }
    return 0;
}

 

资源下载链接为: https://pan.quark.cn/s/1bfadf00ae14 华为移动服务(Huawei Mobile Services,简称 HMS)是一个全面开放的移动服务生态系统,为企业和开发者提供了丰富的工具和 API,助力他们构建、运营和推广应用。其中,HMS Scankit 是华为推出的一款扫描服务 SDK,支持快速集成到安卓应用中,能够提供高效且稳定的二维码和条形码扫描功能,适用于商品扫码、支付验证、信息获取等多种场景。 集成 HMS Scankit SDK 主要包括以下步骤:首先,在项目的 build.gradle 文件中添加 HMS Core 库和 Scankit 依赖;其次,在 AndroidManifest.xml 文件中添加相机访问和互联网访问权限;然后,在应用程序的 onCreate 方法中调用 HmsClient 进行初始化;接着,可以选择自定义扫描界面或使用 Scankit 提供的默认扫描界面;最后,实现 ScanCallback 接口以处理扫描成功和失败的回调。 HMS Scankit 内部集成了开源的 Zxing(Zebra Crossing)库,这是一个功能强大的条码和二维码处理库,提供了解码、生成、解析等多种功能,既可以单独使用,也可以与其他扫描框架结合使用。在 HMS Scankit 中,Zxing 经过优化,以更好地适应华为设备,从而提升扫描性能。 通常,ScanKitDemoGuide 包含了集成 HMS Scankit 的示例代码,涵盖扫描界面的布局、扫描操作的启动和停止以及扫描结果的处理等内容。开发者可以参考这些代码,快速掌握在自己的应用中实现扫码功能的方法。例如,启动扫描的方法如下: 处理扫描结果的回调如下: HMS Scankit 支持所有安卓手机,但在华为设备上能够提供最佳性能和体验,因为它针对华为硬件进行了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值