【备战秋招】每日一题:4月23日美团春招:题面+题目思路 + C++/python/js/Go/java带注释

2023大厂笔试模拟练习网站(含题解)
www.codefun2000.com
最近我们一直在将收集到的各种大厂笔试的解题思路还原成题目并制作数据,挂载到我们的OJ上,供大家学习交流,体会笔试难度。现已录入200+道互联网大厂模拟练习题,还在极速更新中。欢迎关注公众号“塔子哥学算法”获取最新消息。

提交链接:

https://codefun2000.com/p/P1138

为了更好的阅读体检,可以查看OJ上的题解。进入提交链接,点击右边菜单栏的"查看塔子哥的题解"

在线评测链接:P1247

题目内容

塔子哥是一个喜欢种田类的游戏的人,他觉得这样的游戏可以让他体验到农民的乐趣,同时也可以锻炼他的经营能力。他最近在玩一个叫做“农场大亨”的游戏,这个游戏的目的是在有限的时间内赚尽可能多的钱。游戏中有 n 种作物,每种作物都有自己的特点,比如生长周期、种子成本、作物收益等。塔子哥需要根据这些信息,合理地安排自己的种植计划,以达到最大化利润的目标。

塔子哥只有一块土地,也就是说每个时间只能由一个作物在生长。他需要在游戏开始时购买种子,然后种植在土地上。种子的买入价格为 a_i ,作物卖出价格 b_i 。一个种子只会产出一个作物,种子可以重复购买。第 i 种作物从种植到作物成熟采摘需要 t_i 天时间,种植和采摘、卖出等操作不耗时间,成熟之前作物没有价值。如果塔子哥想要更换作物,他需要先把当前作物采摘卖出,然后再购买新的种子。

游戏内总时长为 m 天,也就是说塔子哥只有 m 天的时间来经营自己的农场。塔子哥初始的钱足够多,不用担心资金不足。塔子哥想知道,在这样的条件下,他最多能赚多少钱。

输入描述

第一行两个整数 n ,m (1 \leq n , m \leq 1000)表示作物种类数和游戏时长;

第二行 n 个正整数,表示每种作物的成熟时长 t_i(1 \leq t_i \leq m)

第三行 n 个正整数,表示每种作物的种子价格 a_i(1 \leq a_i \leq 100000)

第四行 n 个正整数,表示每种作物的卖出价格b_i(a_i \leq b_i \leq 100000)

输出描述

输出一个整数来表示塔子哥最多能赚的钱。

样例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]);
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值