【备战秋招】每日一题:2023.3.16-携程OD机试-组装电脑

塔子哥想要升级他的电脑,需要在预算内选择最高性价比的零件。问题转化为在给定价格限制下,使用深度优先搜索(DFS)策略找到性能最高的零件组合。文章提供了多语言的代码示例,包括C++、Python、Java和Go,展示如何实现这个DFS解决方案。
摘要由CSDN通过智能技术生成

为了更好的阅读体检,可以查看我的算法学习网
在线评测链接:P1085

题目内容

塔子哥是一位电脑发烧友,热爱 D I Y DIY DIY组装电脑。他研究了各种零部件,了解到不同型号的零件有不同的性能和价格,而性价比也会有所差异。因此,他需要谨慎地选择零部件,以使他的电脑既具有出色的性能,又不会让他花费太多的钱。

这一次,塔子哥决定升级他的电脑,需要购买 n n n个零件,每个零件有多个型号可供选择。他知道每个型号的价格 a i a_i ai 和性能 v i v_i vi ,并且他有一个限制条件,塔子哥需要每个零件选择一个型号并且总价格不能超过 x x x元。他希望在这个限制条件下,选出的零件能够使他的电脑性能尽可能强大。塔子哥需要你的帮助,来找到最优的选择方案。

输入描述

第一行输入两个正整数 n n n x x x ,代表电脑的零件数量以及塔子哥最大的预算。

接下来的 3 ∗ n 3*n 3n 行,每三行用来描述一个零件的不同型号的价格和性能。

对于每种零件,第一行输入一个正数 m m m ,代表该零件有多少种型号;

第二行输入 m m m 个整数,代表这 m m m 个零件的价格;

第三行输入 m m m 个整数,代表这 m m m 个零件的性能。

1 ≤ n , m ≤ 40 1 \leq n,m \leq 40 1n,m40

1 ≤ a ∗ i , v ∗ i , x ≤ 1 0 9 1 \leq a*_{i},v_*{i},x \leq 10^9 1ai,vi,x109

保证所有 m m m 之和不超过 40 40 40 ,即所有零件的型号数量之和不超过 40 40 40 种。

输出描述

如果无法完成组装,则直接输出 − 1 。 -1。 1

否则输出一个正整数,代表最终最大的性能。

样例

输入

2 3
2
1 3
2 5
2
2 3
2 4

输出

4

说明

一共需要两个零件。

第一个零件选择第一个型号,第二个零件也选择第一个型号。

这样总价格为 3 3 3 ,总性能为 4 4 4

思路:DFS

由题可知,每一种零件都必须选择一个,考虑深搜(dfs)枚举。

具体dfs实现:对于一种零件,循环遍历所有型号,如果说当前所剩下的钱足够买此型号,则递归对下一种零件;否则查看当前零件的下一个型号是否够钱

买。如此递归,直到所有零件都被访问后记录最大性能;

注:在dfs之前,需要把ans初始化为-1,这样做的好处就是如果说没办法递归完所有的零件,则说明无法组装,即ans值不会变

类似题目推荐

CodeFun2000

P1094 2023.03.19-第一题-塔子哥的RBG矩阵

P1074 2023.3.12-第二题-塔子哥卖玩具

P1141 2023.04.01-第五题-染色の树

P1167 2023.04.08-春招-第二题-必经之路

代码

CPP

#include <algorithm>
#include <iostream>
using namespace std;
const int N = 50;
using ll = long long;
ll a[N][N], v[N][N], num[N], ans;
void dfs(int n, ll cost, ll vsum) {
    if (n == 0) { // 递归结束条件:遍历完了所有零件
        ans = max(ans, vsum); // 记录答案
        return;
    }
    for (int i = 1; i <= num[n]; ++i) {
        if (cost >= a[n][i]) { // 如果当前剩下的钱足够购买此型号
            dfs(n - 1, cost - a[n][i], vsum + v[n][i]); // 则递归下一个零件
        }
    }
}

int main() {
    int n, x;
    cin >> n >> x;
    for (int i = 1; i <= n; ++i) {
        int m;
        cin >> m;
        num[i] = m;  // 记录当前零件的个数
        for (int j = 1; j <= m; ++j) { // 记录价格
            cin >> a[i][j];
        }
        for (int j = 1; j <= m; ++j) { // 记录性能
            cin >> v[i][j];
        }
    }
    ans = -1; // 初始化为-1,若dfs不到完所有零件,则ans值不变
    dfs(n, x, 0); // 倒过来递归零件,方便处理
    cout << ans << endl;
    return 0;
}

python

def dfs(n, cost, vsum):
    global ans
    if n == 0:
        ans = max(ans, vsum)  # 记录答案
        return
    for i in range(1, num[n] + 1):
        if cost >= a[n][i]:
            dfs(n - 1, cost - a[n][i], vsum + v[n][i])  # 递归下一个零件

N=50
n, x = map(int, input().split())
a = [[0] * N for _ in range(N)]  # 零件价格
v = [[0] * N for _ in range(N)]  # 零件性能
num = [0] * N  # 每种零件的个数
ans = -1  # 最终答案

for i in range(1, n + 1):
    m = int(input())  # 输入当前零件个数
    num[i] = m  # 记录当前零件的个数
    a[i][1 : m + 1] = map(int, input().split())  # 输入价格
    v[i][1 : m + 1] = map(int, input().split())  # 输入性能

dfs(n, x, 0)  # 逆序递归零件
print(ans)  # 打印最终答案

Java

import java.util.Scanner;

public class Main {
    static final int N = 50;
    static long[][] a = new long[N][N]; // 零件价格
    static long[][] v = new long[N][N]; // 零件性能
    static int[] num = new int[N]; // 每种零件的个数
    static long ans; // 最终答案

    public static void dfs(int n, long cost, long vsum) {
        if (n == 0) {
            ans = Math.max(ans, vsum); // 记录答案
            return;
        }
        for (int i = 1; i <= num[n]; i++) {
            if (cost >= a[n][i]) {
                dfs(n - 1, cost - a[n][i], vsum + v[n][i]); // 递归下一个零件
            }
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int x = scanner.nextInt();

        for (int i = 1; i <= n; i++) {
            int m = scanner.nextInt(); // 输入当前零件个数
            num[i] = m; // 记录当前零件的个数
            for (int j = 1; j <= m; j++) {
                a[i][j] = scanner.nextLong(); // 输入价格
            }
            for (int j = 1; j <= m; j++) {
                v[i][j] = scanner.nextLong(); // 输入性能
            }
        }

        ans = -1; // 初始化答案为 -1
        dfs(n, x, 0); // 逆序递归零件

        System.out.println(ans); // 打印最终答案
    }
}

Go

package main

import (
	"fmt"
)

const N = 50

var a [N][N]int64  // 零件价格
var v [N][N]int64  // 零件性能
var num [N]int     // 每种零件的个数
var ans int64      // 最终答案

func dfs(n int, cost int64, vsum int64) {
	if n == 0 {
		ans = max(ans, vsum) // 记录答案
		return
	}
	for i := 1; i <= num[n]; i++ {
		if cost >= a[n][i] {
			dfs(n-1, cost-a[n][i], vsum+v[n][i]) // 递归下一个零件
		}
	}
}

func max(a, b int64) int64 {
	if a > b {
		return a
	}
	return b
}

func main() {
	var n, x int
	fmt.Scan(&n, &x) // 输入 n 和 x

	for i := 1; i <= n; i++ {
		var m int
		fmt.Scan(&m)     // 输入当前零件个数
		num[i] = m       // 记录当前零件的个数
		for j := 1; j <= m; j++ {
			fmt.Scan(&a[i][j])  // 输入价格
		}
		for j := 1; j <= m; j++ {
			fmt.Scan(&v[i][j])  // 输入性能
		}
	}

	ans = -1   // 初始化答案为 -1
	dfs(n, int64(x), 0)  // 逆序递归零件

	fmt.Println(ans)  // 打印最终答案
}

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');
  const N = 50;
  const num = new Array(N).fill(0); // 每种零件的个数
  const a = new Array(N).fill().map(() => new Array(N).fill(0)); // 零件价格
  const v = new Array(N).fill().map(() => new Array(N).fill(0)); // 零件性能
  let ans = -1; // 初始化为-1,若dfs不到完所有零件,则ans值不变

  let n, x;
  let idx=0;
  [n, x] = lines[0].trim().split(' ').map(Number);
  for (let i=1;i<=n;i++){
    num[i]=Number(lines[++idx]);
    let tmp=lines[++idx].split(' ').map(Number);
    for (let j=1;j<=num[i];j++)
      a[i][j]=tmp[j-1];
    tmp=lines[++idx].split(' ').map(Number);
    for (let j=1;j<=num[i];j++)
      v[i][j]=tmp[j-1];

  }

  dfs(n, x, 0); // 逆序递归零件
  console.log(ans); // 打印最终答案

  // 定义 dfs() 函数以及其他函数
  function dfs(n, cost, vsum) {
    if (n === 0) {
      ans = Math.max(ans, vsum); // 记录答案
      return;
    }
    for (let i = 1; i <= num[n]; ++i) {
      if (cost >= a[n][i]) {
        dfs(n - 1, cost - a[n][i], vsum + v[n][i]); // 递归下一个零件
      }
    }
  }
});

题目内容均收集自互联网,如如若此项内容侵犯了原著者的合法权益,可联系我: (CSDN网站注册用户名: 塔子哥学算法) 进行删除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塔子哥学算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值