为了更好的阅读体检,为了更好的阅读体检,,可以查看我的算法学习博客第三题-农村大亨
在线评测链接:P1247
题目内容
塔子哥是一个喜欢种田类的游戏的人,他觉得这样的游戏可以让他体验到农民的乐趣,同时也可以锻炼他的经营能力。他最近在玩一个叫做“农场大亨”的游戏,这个游戏的目的是在有限的时间内赚尽可能多的钱。游戏中有 n 种作物,每种作物都有自己的特点,比如生长周期、种子成本、作物收益等。塔子哥需要根据这些信息,合理地安排自己的种植计划,以达到最大化利润的目标。
塔子哥只有一块土地,也就是说每个时间只能由一个作物在生长。他需要在游戏开始时购买种子,然后种植在土地上。种子的买入价格为 ,作物卖出价格
。一个种子只会产出一个作物,种子可以重复购买。第 i 种作物从种植到作物成熟采摘需要
天时间,种植和采摘、卖出等操作不耗时间,成熟之前作物没有价值。如果塔子哥想要更换作物,他需要先把当前作物采摘卖出,然后再购买新的种子。
游戏内总时长为 m 天,也就是说塔子哥只有 m 天的时间来经营自己的农场。塔子哥初始的钱足够多,不用担心资金不足。塔子哥想知道,在这样的条件下,他最多能赚多少钱。
输入描述
第一行两个整数 n ,表示作物种类数和游戏时长;
第二行 n 个正整数,表示每种作物的成熟时长 ;
第三行 n 个正整数,表示每种作物的种子价格 ;
第四行 n 个正整数,表示每种作物的卖出价格。
输出描述
输出一个整数来表示塔子哥最多能赚的钱。
样例1
输入
3 12 3 4 7 9 3 2 11 6 11
输出
12
样例解释
赚钱最多的方案是先种一个第二种作物,然后种一个第三种作物,耗时 4+7=11 天,赚的钱数为 6-3+11-2=12 ,可以证明这是最优的方案。
样例2
输入
10 100 81 21 66 63 48 25 23 88 71 65 56 12 94 57 57 6 37 63 87 64 62 68 99 93 88 96 47 65 97 69
输出
360
思路
动态规划-完全背包
对于每种作物,如果种下之后不收获,那么这段时间就是会被浪费的,所以每种作物我们考虑其赚的钱和需要付出的时间。 同时可以重复种同一种作物,那么这就是一个完全背包问题。总游戏时长就是背包容量,单个作物从种下种子到收获卖出的时间就是物品体积,赚到的钱就是物品的价值。
知识点学习
1.动态规划(dp)入门 by 一只会code的小金鱼
推荐理由:由浅入深,从dfs -> 记忆化搜索 -> 动态规划 的思路来讲解dp。也是公认的比较符合人类思维的理解dp的过程。
2.闫氏DP分析法
推荐理由:一套固定的分析动态规划的模式,清晰易懂。掌握这套分析法,可以解决更复杂的dp问题
3.背包九讲专题 by yxc
推荐理由:配合闫氏DP分析法,可以很好的掌握几大背包问题。
4.[算法竞赛入门] 容斥原理与组合计数 (蒋炎岩)
推荐理由:数学观点(集合论+组合数学)下的动态规划。
类似题目推荐
虽然有这么多学习视频,但是动态规划的分析也十分依赖经验 。所以一定一定要多刷题
Leetcode
代码随想录 - 动态规划专题
CodeFun2000
1.P1178. 2023.04.09-小红书春招-第二题-融合试剂 -类背包问题
2.P1212. 塔子大厂真题模拟赛-第二题-魔法石(Ⅱ) - 分组背包
3.P1025. 2022.11.9-华为秋招-攻城战 - 分组背包
4.P1090. 2023.3.18.10点-美团-第四题-提瓦特商店 -二维背包
更多大厂考察动态规划的真题见知识点分类训练 中的动态规划转题
代码
CPP
#include <bits/stdc++.h>
using namespace std;
const int N = 1010, M = 1010;
int f[M];
int n, m;
int v[N], w[N];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) scanf("%d", &v[i]);
for (int i = 1; i <= n; ++i) scanf("%d", &w[i]);
for (int i = 1; i <= n; ++i) {
int x; scanf("%d", &x);
w[i] = x - w[i];
}
for (int i = 1; i <= n; ++i)
for (int j = v[i]; j <= m; ++j) {
f[j] = max(f[j], f[j - v[i]] + w[i]);
}
printf("%d\n", f[m]);
return 0;
}
Java
import java.util.Scanner;
public class Main {
static final int N = 1010, M = 1010;
static int[] f = new int[M];
static int[] v = new int[N];
static int[] w = new int[N];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
for (int i = 1; i <= n; ++i) v[i] = sc.nextInt();
for (int i = 1; i <= n; ++i) w[i] = sc.nextInt();
for (int i = 1; i <= n; ++i) {
int x = sc.nextInt();
w[i] = x - w[i];
}
for (int i = 1; i <= n; ++i) {
for (int j = v[i]; j <= m; ++j) {
f[j] = Math.max(f[j], f[j - v[i]] + w[i]);
}
}
System.out.println(f[m]);
}
}
Python
N, M = 1010, 1010 f = [0] * M n, m = map(int, input().split()) v = list(map(int, input().split())) w = list(map(int, input().split())) w2 = list(map(int, input().split())) for i in range(0, n): w[i] = w2[i] - w[i] for i in range(0, n): for j in range(v[i], m+1): f[j] = max(f[j], f[j - v[i]] + w[i]) print(f[m])
Go
package main
import "fmt"
func main() {
M := 1010
f := make([]int, M)
var n, m int
fmt.Scan(&n, &m)
v := make([]int, n)
for i := 0; i < n; i++ {
fmt.Scan(&v[i])
}
w := make([]int, n)
for i := 0; i < n; i++ {
fmt.Scan(&w[i])
}
w2 := make([]int, n)
for i := 0; i < n; i++ {
fmt.Scan(&w2[i])
}
for i := 0; i < n; i++ {
w[i] = w2[i] - w[i]
}
for i := 0; i < n; i++ {
for j := v[i]; j <= m; j++ {
f[j] = max(f[j], f[j-v[i]]+w[i])
}
}
fmt.Println(f[m])
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
Js
process.stdin.resume();
process.stdin.setEncoding('utf-8');
let input = '';
process.stdin.on('data', (data) => {
input += data;
return;
});
process.stdin.on('end', () => {
const lines = input.trim().split('\n');
var [N , M] = [1010 , 1010];
var f = new Array(M).fill(0);
var [n , m] = lines[0].split(' ').map(Number);
var v = lines[1].split(' ').map(Number);
var w = lines[2].split(' ').map(Number);
var w2 = lines[3].split(' ').map(Number);
for (var i = 0 ; i < n ; i++) w[i] = w2[i] - w[i];
for (var i = 0 ; i < n ; i++){
for (var j = v[i] ; j <= m ; j++){
f[j] = Math.max(f[j] , f[j - v[i]] + w[i])
}
}
console.log(f[m]);
})













