信息学奥赛一本通 1272:【例9.16】分组背包 题解

3 篇文章 0 订阅
1 篇文章 0 订阅

让我们先看一下题目~

【题目链接】

信息学奥赛一本通(C++版)在线评测系统 1272:【例9.16】分组背包http://ybt.ssoier.cn:8088/problem_show.php?pid=1272

【题目描述】 

【输入及输出】 【输入及输出样例】

接下来就是我们的正文啦~

【题目考点】

动态规划:分组背包

【题目类型】

分组背包问题(不用想都知道)

【解题思路】

PS:该解题思路来自君义_noip的博客,博客链接:点我跳转~

分组背包问题,特点是:每组中的物品最多可以取一件

1. 状态定义

  • 集合:放入背包的物品方案

  • 限制:物品所在分组的区间,背包大小

  • 属性:价值

  • 条件:最大

  • 统计量:价值

  • 状态定义:dp[i][j]: 在前i组物品中选择物品放入大小为j的背包能获得的最大价值。

2. 状态转移方程

  • 记第i组物品有m个,这m个物品的编号为i1,i2,…,im。第i物品的重量是w[i],价值是c[i]。

  • 集合:在前i组物品中选择物品放入大小为j的背包的所有方案

  • 分割集合:第i组物品如何放入背包

  • 如果不选择第i组物品,那么在剩余i-1组中选择物品放入大小为j的背包。dp[i][j] = dp[i-1][j]

  • 如果选择第i组物品中的第1个,该物品下标为i1。那么需要在剩余i-1组中选择物品放入大小为j-w[i1]的背包。dp[i][j] = dp[i-1][j-w[i1]]+c[i1]

  • 如果选择第i组物品中的第2个,该物品下标为i2。那么需要在剩余i-1组中选择物品放入大小为j-w[i2]的背包。dp[i][j] = dp[i-1][j-w[i2]]+c[i2]

  • 如果选择第i组物品中的第m个,该物品下标为im。那么需要在剩余i-1组中选择物品放入大小为j-w[im]的背包。dp[i][j] = dp[i-1][j-w[im]]+c[im]

  • 一般地,如果选择第i组物品中的第k个,该物品下标为x。那么需要在剩余i-1组中选择物品放入大小为j-w[x]的背包。dp[i][j] = dp[i-1][j-w[x]]+c[x]。遍历第i组物品,求选择该组中每个物品后能得到的最大价值dp[i][j]。

  • 以上所有情况求最大值。

3. 复杂度分析

背包容量为V,物品总数量为N,分组数量为T。

分组背包一般解法:

滚动数组优化后:

  • 空间复杂度:O(V)

【代码】

#include<bits/stdc++.h>
using namespace std;
int d[210],w[15][40],c[15][40],v,n,len[15],t;
int main()
{
	cin>>v>>n>>t;
	for(int i=1;i<=n;i++)
	{
		int tw,tc,tt;
		cin>>tw>>tc>>tt;
		len[tt]++;
		w[tt][len[tt]]=tw;
		c[tt][len[tt]]=tc;
	}
	for(int i=1;i<=t;i++)
	{
		for(int j=v;j>=0;j--)
		{
			for(int k=1;k<=len[i];k++)
			{
				if(j>=w[i][k])
				{
					d[j]=max(d[j],d[j-w[i][k]]+c[i][k]);
				}
			}
		}
	}
	cout<<d[v];
	return 0;
}

【测评结果】

 PS:这次尝试了不同的方式写题解,请问你们觉得以前那种写法好还是现在的写法好?欢迎在文章底下评论,谢谢。

The end~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值