为了更好的阅读体检,为了更好的阅读体检,,可以查看我的算法学习博客第三题-农村大亨
在线评测链接: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]); })