首页 > 编程语言 >01背包问题/Ieee全球极限编程大赛11.0题BeetleBag题解/洛谷P1926 小书童——刷题大军题解

01背包问题/Ieee全球极限编程大赛11.0题BeetleBag题解/洛谷P1926 小书童——刷题大军题解

时间:2024-10-13 23:21:02浏览次数:10  
标签:01 power 小书童 int 题解 物体 fighting 背包 dp

基础01背包问题

概述

给出一个容积为V的背包,有i个物体,每个物体都有自己的体积和价值,用Vi和Wi表示,要将这些物体装进背包里面,问怎样才能使得装入物体的总价值最大?最大为多少?

解决思路

1.如果你没能正确理解这道题,尤其是对于很多新手,第一反应可能是将所有物体的单位价值算出来,然后按从大到小排序,将单位价值高的物体优先放入背包······

我们来举个例子:现在你的背包体积为10,现在有4个物体,体积分别为1,3,5,7,价值分别为1,4,15,18;如果按单位价值来算15/5>18/7>4/3>1/1,所以现将体积为5的物体放入背包,那么接下来就只能依次放入体积为3和1的物体,这样的话总价值为20,但是显然放入体积为7和3的物体,总价值为22是最大的,那么这种放的方式怎么用算法表示出来呢?

2.算法思路:根据动态规划解题步骤(问题抽象,建立模型,寻找约束条件,判断是否满足最优解原理,找大问题与小问题的递推关系式,填表,寻找解组成)找出01背包问题的最优解及解组成,然后编写代码实现。动态规划其实就是把大问题拆解成一个个的小问题,通过寻找大问题与小问题的递推关系,解决一个个的小问题,最终达到解决大问题的效果,且动态规划的优点在于填表(具有记忆性),可以理解成表中记录每个局部最优然后最终得到全局最优。

3.什么是填表:就是依次将背包容积从1开始递增,记录每一个容积下的最优解,然后通过该最优解推导下一个容积的最优解。这就涉及到一个嵌套循坏了,不仅要将体积从1开始递增,还需要将物体从第一个开始递增,即:将第一次循环只考虑第一个物体,遍历所有的容积,天第一行表,第二次循环考虑前两个物体,遍历所有体积,填第二行表·····(有多少个物体就填多少行表,一共有背包的总容积V列 ,每一行都从体积为1开始填一直到体积为V)

4.大问题与小问题的递推关系式:若有n个物体,背包总容积为m,由上述分析可知这个表应该为n*m(实际上要为(n+1)*(m+1)因为要初始化边缘行列为0),用dp[i][j]来表示该表的第i行第j列(表示考虑放前i个物体且背包容量为j时的最大放入价值)

对于每一个dp[i][j]每次就只需要考虑两种情况:

①背包体积不够放入第i个物体,则dp[i][j]=dp[i-1][j];

②背包体积足够放入第i个物体,但是放入之后剩余体积就变小了,所以需要联系上一行体积相同时的最大价值再加上i的价值和dp[i-1][j]进行比较,

即:dp[i][j]=max(dp[i-1][j],dp[i-1][j-Vi]+Wi)

5.最优解回溯:

①dp[i][j]=dp[i-1][j]时,说明没有选择第i个物体,则回到dp[i-1][j];

②dp[i][j]=dp[i-1][j-Vi]+Wi时,说明选择了第i个物体,该物体是最优解的组成部分,随后我们回到选择该物体之前,即dp[i-1][j-Vi];

③一直遍历到i=0结束为止,所有组成的解都会被找到

例题1:Ieee全球极限编程大赛11.0题BeetleBag

题目:

Beetleman joined the Strangers, a team of super heroes who protect cyber world.

In order to increase Beetleman's fighting power, Copperman allowed Beetleman to choose gadgets from his labs freely.

However, Beetleman has limited space in his hero bag.

Your task is to help Beetleman choose gadgets to increase his fighting power as much as possible.

Standard input

The first line of input has one integer tt (1≤t≤251≤t≤25), the number of test cases that will follow.

For each tt there will be a line that contains two integers, number cc (1≤c≤5001≤c≤500), the capacity of Beetleman's bag, and number nn (1≤n≤2001≤n≤200), the number of gadgets in Copperman labs.

Then for each above line, there will be nn lines that will contain two integers, the number ww (1≤w≤1001≤w≤100), the gadget's weight and the number ff (1≤f≤1 0001≤f≤1000), the fighting power of the gadget.

Standard output

Output will have tt lines containing the maximum fighting power from Copperman's gadgets that can fit into Beetleman's bag.

Constraints and notes

  • 1≤t≤251≤t≤25
  • 1≤c≤5001≤c≤500
  • 1≤n≤2001≤n≤200
  • 1≤wi≤1001≤wi​≤100 for 1≤i≤n1≤i≤n
  • 1≤fi≤1 0001≤fi​≤1000 for 1≤i≤n1≤i≤n
InputOutputExplanation
2
6 2
1 17
6 15
5 5
1 1
2 2
3 3
4 4
5 5
17
5

Input explanation

1

2

4

5

6

7

8

9

10

11

2 <<<< two test cases

6 2 <<<< the first test

    case has 6 capacity

    and 2 gadgets to

    choose from.

1 17 <<<< weight 1,

    fighting power 17

6 15 <<<< weight 6,

    fighting power 15

5 5 <<<< the second test

    case has 5 capacity

    and 5 gadgets to

    choose from.

1 1 <<<< weight 1,

    fighting power 1

2 2 <<<< weight 2,

    fighting power 2

3 3 <<<< weight 3,

    fighting power 3

4 4 <<<< weight 4,

    fighting power 4

5 5 <<<< weight 5,

    fighting power 5

Output explanation

2

3

17 <<<< maximum fighting

    power from first test

    case

5 <<<< maximum fighting

    power from second test

    case

代码:

#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;

int findx(int c,int n,const vector<vector<int> >& s){
	vector<vector<int> >dp(n+1,vector<int>(c+1,0));
	for(int i=1;i<=n;i++){
		for(int x=1;x<=c;x++){
			if(x<s[i-1][0])dp[i][x]=dp[i-1][x];	
			else{
				dp[i][x]=max(dp[i-1][x],dp[i-1][x-s[i-1][0]]+s[i-1][1]);
			}
		}
	}
	return dp[n][c];
}

int main(){
	int t;
	cin>>t;
	vector<int>result(t);
	int c,n;
	for(int i=0;i<t;i++){
		cin>>c>>n;
		vector<vector<int> >p(n+1,vector<int>(2,0));
		for(int z=0;z<n;z++){
			cin>>p[z][0]>>p[z][1];
		}
		result[i]=findx(c,n,p);
	}
	for(int i=0;i<t;i++){
		cout<<result[i]<<endl;
	}
	return 0;
}

例题2:洛谷P1926 小书童——刷题大军(P1926 小书童——刷题大军 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目:

题目描述

小 A “刷题”十分猖狂,明目张胆地“刷题”。他现在在小书童里发现了 nn 样他喜欢的“题目”,每“题”都有他的需要时间,而老师布置了 mm 项作业,每项作业都有它的需要时间及分值,老师规定 kk 分以上算及格。小 A 只剩 rr 个单位时间,他想在及格的基础上更多地“刷题”。

输入格式

第一行四个整数 n,m,k,rn,m,k,r。

第二行有 nn 个数,代表每“题”他的需要时间。

第三行有 mm 个数,表示每项作业它的需要时间。

第四行有 mm 个数,代表每项作业它的分值。

输出格式

一个数,代表小 A 能刷几道题。

输入输出样例

输入 #1复制

3 4 20 100
15 20 50
10 15 40 40
5 5 10 15

输出 

2

说明/提示

数据范围及约定

对于 100%100% 的数据,n≤10n≤10,m≤10m≤10,k≤50k≤50,r≤150r≤150。数据保证没有不能及格的情况。

代码:

//数学是火,点亮物理的灯;物理是灯,照亮化学的路;化学是路,通向生物的坑;生物是坑,埋葬学理的人。
//文言是火,点亮历史宫灯;历史是灯,照亮社会之路;社会是路,通向哲学大坑;哲学是坑,埋葬文科生。 
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
int main(){
	int n,m,k,r;
	cin>>n>>m>>k>>r;
	vector<int> N(n+1,0);
	vector<int> MT(m+1,0);
	vector<int> MF(m+1,0);
	for(int i=1;i<=n;i++){
		cin>>N[i];
	}
	for(int i=1;i<=m;i++){
		cin>>MT[i];
	}
	for(int i=1;i<=m;i++){
		cin>>MF[i];
	}
	vector<vector<int> >dp(m+1,vector<int>(r+1,0));
	int cont=0;
	for(int i=1;i<=m;i++){
		for(int j=1;j<=r;j++){
			if(j<MT[i])dp[i][j]=dp[i-1][j];
			else{
				dp[i][j]=max(dp[i-1][j],dp[i-1][j-MT[i]]+MF[i]);
			}
			if(dp[i][j]>=k && i==m){
				cont=r-j;
				break;
			}
		}
		if(cont!=0)break;
	}
	sort(N.begin()+1,N.end());
	int result=0;
	for(int i=1;i<=n;i++){
		if(cont>=N[i]){
			result++;
			cont-=N[i];
		}	
		else break;
	}
	cout<<result<<endl;
	return 0;
}

交流讨论

以上均为个人粗浅见解,若有错误和改进之处,欢迎在评论区交流讨论

若代码有不清楚或者改进之处,也欢迎留言!

标签:01,power,小书童,int,题解,物体,fighting,背包,dp
From: https://blog.csdn.net/R_world2022/article/details/142904094

相关文章

  • 带中位数写法的快速排序再讨论 & leetcode 215. Kth Largest Element in an Array题解
    带中位数写法的快速排序再讨论&leetcode215.KthLargestElementinanArray题解 探讨带中位数的写法本身classSolution{public:intfindKthLargest(std::vector<int>&nums,intk){returnfakeQuickSort(nums,k,0,nums.size()-1);}privat......
  • ABC375 (A~G) 题解
    也是补完整场了。(虽然只有一题要补A模拟。B模拟。C模拟。D模拟。EE-3TeamDivision还想了蛮久的。题意:有三个队伍,各有一些人,人有能力值,人可以换队伍。问三个队伍能力值相同最少需要让多少人交换队伍。人数\(\le100\),值域\(\le1500\)题目还是挺误导人的,如......
  • [JLOI2015] 有意义的字符串 题解
    看到这个\(7\times10^{18}\)的模数已经可以摆烂了。不是,你告诉我这东西跟矩阵快速幂优化DP有关系??观察到这个题显然不能硬做,因为你显然不能直接算小数部分,而且还有个取模很难受。所以我们希望把一切的计算都基于整数。这个时候我们就要思考,有什么东西可以把根号转化为整数......
  • 【妙趣横生】01_C语言的指针是啥?为啥那么难懂?
      引入:C语言的指针是啥?为啥那么难懂?C语言中的指针是C语言的一个核心概念,也是其强大和灵活性的重要来源之一。然而,对于初学者来说,指针确实可能是一个难以理解的概念。下面我会尽量用简单的语言来解释什么是C语言中的指针,以及为什么它可能会让人觉得难懂。趣味解释:C语言......
  • Codeforces Round 899 (Div. 2)题解记录
    题目链接:https://codeforces.com/contest/1882A.IncreasingSequence从1开始慢慢和\(a[i]\)的所有值比较,注意最后一个位置特判下#include<iostream>#include<string.h>#include<map>#include<vector>#include<set>#include<unordered_set>#include<......
  • 2024.10.13 2010版
    起于《海奥华预言》的思考◆地球管理结构和参考持续更新中...... 英文地址:https://github.com/zhuyongzhe/Earth/tags中文地址:https://www.cnblogs.com/zhuyongzhe85作者:朱永哲 ---------------------------------------------------------------------------------......
  • Centos7---k8s集群 20241013
    目录一、硬件准备(虚拟主机)二、环境准备1、所有机器关闭防火墙2、所有机器关闭selinux3、所有机器关闭swap4、所有机器上添加主机名与ip的对应关系5、在所有主机上将桥接的ipv4流量传递到iptables的链三、为所有节点安装docker四、集群部署1、为所有节点修改仓库,安......
  • day01-面向对象高级
    day01——面向对象高级各位同学,接下来的三天课程中,我们继续学习面向对象的相关课程。面向对象是写Java程序的核心套路,如何你不懂面向对象,那就相当于Java你白学了。所以在接下来的三天时间里,各位同学也需要克服重重困难好好学习。前面我们说过面向对象最核心的套路是:设计对象来处......
  • Linux快速入门知识点概括01
    前提当在阅读这篇文章的时候,这里默认已经购买过云服务器或者在本地搭建了虚拟机环境1、预热关机:shutdownshutdown-h10#10分钟之后关机shutdown-hnow#立马关机shutdown-h20:14#会在20点14分关机shutdown-h+10#十分钟后关机shutdown-rnow#立马重启shutdown-......
  • 2024-2025-1 20241301 《计算机基础与程序设计》第3周学习总结
    这个作业属于哪个课程<2024-2025-1-计算机基础与程序设计>这个作业要求在哪里https://www.cnblogs.com/rocedu/p/9577842.html#WEEK03这个作业的目标<回顾本周所学知识,夯实基础>作业正文...https://www.cnblogs.com/HonJo/p/18462585教材学习内容总结1.门......