本文主要是介绍算法学习系列(五十一):背包模型(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
- 引言
- 一、采药
- 二、装箱问题
- 三、宠物小精灵之收服
引言
关于 背包问题 可以参考我之前的博客,由于基础的算法和模板已经学过了,所以现在就是开始学模型了,难点就是阅读理解、抽象模型、代码熟练度、心理素质也就是这几个难点了,其实就是多练就好了,加油!
一、采药
标签:DP、01背包问题
思路:
就是一道很裸的 01 01 01 背包问题,我们把时间看作背包的容积,数量看作物品的个数,并且每件物品只能选一次,所以直接拿模板去解就行了。这里的写法跟之前的不太一样,我们发现每次的 w [ i ] , v [ i ] w[i],v[i] w[i],v[i] 其实就是该次的,不用存直接在输入的时候就一读,之后也就不用了,所以可以用如下的写法。
题目描述:
辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它
自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的
总价值最大。”如果你是辰辰,你能完成这个任务吗?输入格式
输入文件的第一行有两个整数 T 和 M,用一个空格隔开,T 代表总共能够用来采药的时间,M 代表山洞里的草药的数目。接下来的 M 行每行包括两个在 1 到 100 之间(包括 1 和 100)的整数,分别表示采摘某株草药的时间和这株草药的价值。输出格式
输出文件包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。数据范围
1≤T≤1000,1≤M≤100
输入样例:
70 3
71 100
69 1
1 2
输出样例:
3
示例代码:
#include <bits/stdc++.h>using namespace std;typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y secondconst int N = 110, M = 1010;int n, m;
int f[M];int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> m >> n;for(int i = 1; i <= n; ++i){int v, w; cin >> v >> w;for(int j = m; j >= v; --j){f[j] = max(f[j], f[j-v]+w);}}cout << f[m] << endl;return 0;
}
二、装箱问题
标签:DP、01背包问题
思路:
这个背包问题其实就是一个组合问题,问在满足条件的情况下,什么样的组合能使得某个值最大。这道题首先每个物品只能选择一次,所以判断是 01 01 01 背包,然后容量就是题意,问的是剩余空间最小,也就是装入的体积最大,也就是将体积看作价值了,求价值最大,也就是模板了,跟上一题一样。
题目描述:
有一个箱子容量为 V,同时有 n 个物品,每个物品有一个体积(正整数)。要求 n 个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。输入格式
第一行是一个整数 V,表示箱子容量。第二行是一个整数 n,表示物品数。接下来 n 行,每行一个正整数(不超过10000),分别表示这 n 个物品的各自体积。输出格式
一个整数,表示箱子剩余空间。数据范围
0<V≤20000,0<n≤30
输入样例:
24
6
8
3
12
7
9
7
输出样例:
0
示例代码:
#include <bits/stdc++.h>using namespace std;typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y secondconst int N = 2e4+10;int n, m;
int f[N];int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> m >> n;for(int i = 1; i <= n; ++i){int v; cin >> v;for(int j = m; j >= v; --j){f[j] = max(f[j], f[j-v]+v);}}cout << m - f[m] << endl;return 0;
}
三、宠物小精灵之收服
标签:DP、01背包问题、阅读理解
思路:
这道题相当于是有两个体积,然后剩余的就跟模板一样,然后注意这里的体积二不能被取满,因为取满所包含的那个数不算,当然也有可能算这个体积最后的值也没有变化,所以这里直接取 f [ V 1 ] [ V 2 − 1 ] f[V1][V2-1] f[V1][V2−1] 即可。然后第二问求的是最优解的情况下体积二最小是多少,那直接拿循环判断即可,详情见代码。
题目描述:
宠物小精灵是一部讲述小智和他的搭档皮卡丘一起冒险的故事。一天,小智和皮卡丘来到了小精灵狩猎场,里面有很多珍贵的野生宠物小精灵。小智也想收服其中的一些小精灵。然而,野生的小精灵并不那么容易被收服。对于每一个野生小精灵而言,小智可能需要使用很多个精灵球才能收服它,而在收服过程中,野生小精灵也会对皮卡丘造成一定
的伤害(从而减少皮卡丘的体力)。当皮卡丘的体力小于等于0时,小智就必须结束狩猎(因为他需要给皮卡丘疗伤),而使得皮卡丘体力小于等于0的野生小精灵也
不会被小智收服。当小智的精灵球用完时,狩猎也宣告结束。我们假设小智遇到野生小精灵时有两个选择:收服它,或者离开它。如果小智选择了收服,那么一定会扔出能够收服该小精灵的精灵球,而皮卡丘也一定会受到相应的伤害;如果选择离开它,那么
小智不会损失精灵球,皮卡丘也不会损失体力。小智的目标有两个:主要目标是收服尽可能多的野生小精灵;如果可以收服的小精灵数量一样,小智希望皮卡丘受到的伤害越小
(剩余体力越大),因为他们还要继续冒险。现在已知小智的精灵球数量和皮卡丘的初始体力,已知每一个小精灵需要的用于收服的精灵球数目和它在被收服过程中会对皮卡
丘造成的伤害数目。请问,小智该如何选择收服哪些小精灵以达到他的目标呢?输入格式
输入数据的第一行包含三个整数:N,M,K,分别代表小智的精灵球数量、皮卡丘初始的体力值、野生小精灵的数量。之后的K行,每一行代表一个野生小精灵,包括两个整数:收服该小精灵需要的精灵球的数量,以及收服过程中对皮卡丘造成的
伤害。输出格式
输出为一行,包含两个整数:C,R,分别表示最多收服C个小精灵,以及收服C个小精灵时皮卡丘的剩余体力值最多为R。数据范围
0<N≤1000,0<M≤500,0<K≤100
输入样例1:
10 100 5
7 10
2 40
2 50
1 20
4 20
输出样例1:
3 30
输入样例2:
10 100 5
8 110
12 10
20 10
5 200
1 110
输出样例2:
0 100
示例代码:
#include <bits/stdc++.h>using namespace std;typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y secondconst int N = 1010, M = 510;int V1, V2, n;
int f[N][M];int main()
{ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> V1 >> V2 >> n;for(int i = 1; i <= n; ++i){int v1, v2; cin >> v1 >> v2;for(int j = V1; j >= v1; --j){for(int k = V2; k >= v2; --k){f[j][k] = max(f[j][k], f[j-v1][k-v2]+1);}}}int res = f[V1][V2-1];cout << res << " ";int k = V2 - 1;while(k >= 0 && f[V1][k] == res) k--;cout << V2 - k - 1 << endl;return 0;
}
这篇关于算法学习系列(五十一):背包模型(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!