首页 > 编程语言 >【代码+详解】算法题 : 金银岛

【代码+详解】算法题 : 金银岛

时间:2024-06-12 11:59:29浏览次数:13  
标签:weight int testCases metals 金属 算法 详解 value 金银岛

❗❗❗必看:
下列题我全部都使用 Java 语言写的,并且均可以提交成功,获得Accepted 结果的. 如果代码和详解看了之后,对答案有任何疑问,都可以在评论区提出来,我都会一个一个回答.

❗❗❗感谢大家的支持,如果喜欢我的博客,关注 点赞 收藏 评论一波,非常感谢!!!

文章目录

题目:金银岛

某天KID利用飞行器飞到了一个金银岛上,上面有许多珍贵的金属,KID虽然更喜欢各种宝石的艺术品,可是也不拒绝这样珍贵的金属。但是他只带着一个口袋,口袋至多只能装重量为w的物品。岛上金属有s个种类, 每种金属重量不同,分别为n(1), n(2), … , n(s),同时每个种类的金属总的价值也不同,分别为v(1),v(2), …, v(s)。KID想一次带走价值尽可能多的金属,问他最多能带走价值多少的金属。注意到金属是可以被任意分割的,并且金属的价值和其重量成正比。

Input

第1行是测试数据的组数k,后面跟着k组输入。

每组测试数据占3行,第1行是一个正整数w (1 <= w <= 10000),表示口袋承重上限。第2行是一个正整数s (1 <= s <=100),表示金属种类。第3行有2s个正整数,分别为n(1), v(1), n(2), v(2), … , n(s), v(s)分别为第一种,第二种,…,第s种金属的总重量和总价值(1 <= n(i) <= 10000, 1 <= v(i) <= 10000)。

Output

k行,每行输出对应一个输入。输出应精确到小数点后2位。

样例测试

输入

2
50
4
10 100 50 30 7 34 87 100
10000
5
1 43 43 323 35 45 43 54 87 43

输出

171.93
508.00

代码

import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int k = sc.nextInt(); // 读取测试数据的组数
        List<int[]> testCases = new ArrayList<>();

        for (int i = 0; i < k; i++) {
            int w = sc.nextInt(); // 读取口袋承重上限
            int s = sc.nextInt(); // 读取金属种类
            int[] metals = new int[2 * s + 2];
            metals[0] = w;
            metals[1] = s;
            for (int j = 2; j < 2 * s + 2; j++) {
                metals[j] = sc.nextInt(); // 读取每种金属的重量和价值
            }
            testCases.add(metals);
        }

        List<String> results = maxMetalValue(k, testCases);
        for (String result : results) {
            System.out.println(result); // 输出结果
        }
        sc.close();
    }

    public static List<String> maxMetalValue(int k, List<int[]> testCases) {
        List<String> results = new ArrayList<>();

        for (int i = 0; i < k; i++) {
            int w = testCases.get(i)[0];
            int s = testCases.get(i)[1];
            int[] metals = Arrays.copyOfRange(testCases.get(i), 2, testCases.get(i).length);

            List<Metal> metalList = new ArrayList<>();
            for (int j = 0; j < s; j++) {
                int weight = metals[2 * j];
                int value = metals[2 * j + 1];
                metalList.add(new Metal(weight, value));
            }

            metalList.sort((m1, m2) -> Double.compare(m2.unitValue, m1.unitValue));

            double totalValue = 0.0;
            for (Metal metal : metalList) {
                if (w <= 0) break;
                if (metal.weight <= w) {
                    totalValue += metal.value;
                    w -= metal.weight;
                } else {
                    totalValue += metal.unitValue * w;
                    w = 0;
                }
            }

            results.add(String.format("%.2f", totalValue)); // 这里进行格式化并添加到结果中
        }

        return results;
    }

    static class Metal {
        double unitValue;
        int weight;
        int value;

        public Metal(int weight, int value) {
            this.weight = weight;
            this.value = value;
            this.unitValue = (double) value / weight;
        }
    }
}

图示

画的有点抽象,但是非常建议把下面的图示结合代码一起看,学起来的效率非常高.保证一看就会

在这里插入图片描述

金银岛算法题解

初步思路

这个问题是典型的“贪心算法”应用。通过计算每种金属的单位价值(即每单位重量的价值),然后优先选择单位价值最高的金属直到达到口袋承重上限,可以最大化KID能带走的金属总价值。

具体步骤

  1. 读取输入数据:从输入中读取测试数据的组数k,之后对每组测试数据分别处理。
  2. 数据解析:对每组测试数据,先读取口袋承重上限w,然后读取金属种类数s,接着读取每种金属的重量和价值。
  3. 计算单位价值:为每种金属计算单位价值(即每单位重量的价值 = 总价值 / 总重量)。
  4. 按单位价值排序:将金属按单位价值从高到低排序。
  5. 贪心选择:从单位价值最高的金属开始,尽量多地选择直到达到承重上限。如果当前金属重量超过剩余承重上限,则选择部分金属使其正好达到承重上限。
  6. 记录结果:记录每组测试数据的最大金属总价值,并格式化到小数点后两位。

总结方法

这种方法的关键在于贪心选择的策略,通过单位价值的排序和逐步选择,确保每一步都尽可能提高总价值。这样的策略在面对能够部分选择的物品问题时非常有效。通过这一题,我们可以更好地理解贪心算法在解决部分选择问题中的应用,并学习如何通过排序和逐步选择来达到最优解。

标签:weight,int,testCases,metals,金属,算法,详解,value,金银岛
From: https://blog.csdn.net/weixin_75202470/article/details/139576612

相关文章

  • 网络安全学习路线图(2024版详解)
     近期,大家在网上对于网络安全讨论比较多,想要学习的人也不少,但是需要学习哪些内容,按照什么顺序去学习呢?其实我们已经出国多版本的网络安全学习路线图,一直以来效果也比较不错,本次我们针对市场需求,整理了一套系统的网络安全学习路线图,供大家学习参考。希望大家按照路线图进行系统......
  • 14款测试用例管理工具详解
    14款不错的测试用例管理工具对比:PingCode、TestRAIl、Xray、PractiTest、TricentisqTest、禅道(ZenTao)、Zephyr、Tapd、TestLink、TestCollab、Testin云测、云效(AlibabaCloudEffect)、TeavCloud、FitNesse。在软件开发过程中,测试用例管理工具的使用变得越来越重要。这些工具......
  • 【近邻算法】近邻算法详解——深入理解K-近邻(KNN)
    目录1引言2算法基础2.1核心原理2.2算法步骤3关键参数与优化3.1K值选择3.2距离度量4优缺点分析4.1优点4.2缺点5改进策略6应用案例深度解析:K-近邻算法在客户细分中的应用6.1引言6.2数据准备与预处理6.3特征选择与编码6.4K-近邻算法应用6.5模型......
  • 100个常用Shell使用命令详解
    转载自公众号:一口Linux 在大多数的Linux和Unix系统、及其他类Unix系统中,Shell是用户与操作系统内核交互的主要方式。作为一种强大的命令行解释器,它也支持编程功能,用户可以写脚本来处理各种任务。无论是新手还是专业人士,掌握Shell命令都是必不可少的技能。本文逐个解读和展示Sh......
  • 一种改进盲解卷积算法在旋转机械故障诊断中的应用(MATLAB)
    滚动轴承故障形成后,故障区与其他零部件表面接触将产生循环平稳的瞬态脉冲。由于受到系统传递函数、轴转频和环境噪声的干扰,故障脉冲特征受到大幅衰减,在测得信号中表现十分微弱甚至完全不可见。盲解卷积算法通过搜索一个最优的有限脉冲响应滤波器来降低信号传输路径、轴转频和环......
  • 实现EM算法的单次迭代过程
    编程要求根据提示,在右侧编辑器补充Begin-End段中的代码,完成em_single(priors,observations)函数。该函数需要完成的功能是模拟抛掷硬币实验并估计在一次迭代中,硬币A与硬币B正面朝上的概率。其中:init_values:硬币A与硬币B正面朝上的概率的初始值,类型为list,如[......
  • 如何评估pcdn调度算法的优化效果(贰)
    PCDN(PersonalizedContentDeliveryNetwork)调度算法的优化可以通过以下几个方面来进行:1、性能指标:首先确定要评估的关键性能指标(KPIs),如平均响应时间、内容分发速度、缓存命中率、用户满意度等。这些指标应直接反映算法优化后的效果。2、基准测试:在优化之前,进行基准测试以......
  • 第6篇:Milvus检索算法详解:从原理到应用
    欢迎来到Milvus检索算法的世界!在本文,我将带你深入了解Milvus的向量相似度计算和常用的检索算法。通过这篇博客,你将了解Milvus是如何高效计算向量相似度并进行向量检索的。准备好了吗?让我们开始这段知识之旅吧!文章目录Milvus的向量相似度计算向量相似度计算的原理......
  • TCP四次挥手全过程详解
    TCP四次挥手全过程有几点需要澄清:1.首先,tcp四次挥手只有主动和被动方之分,没有客户端和服务端的概念2.其次,发送报文段是tcp协议栈的行为,用户态调用close会陷入到内核态3.再者,图中的情况前提是双方程序正常运行,程序在挥手过程中崩溃的情况后面会讲到过程详解(时间顺序)1.......
  • 代码随想录算法训练营第第35天 | 977.有序数组的平方1005.K次取反后最大化的数组和 、
    1005.K次取反后最大化的数组和本题简单一些,估计大家不用想着贪心,用自己直觉也会有思路。https://programmercarl.com/1005.K次取反后最大化的数组和.html自己写的时间复杂度太高,看答案优化/***@param{number[]}nums*@param{number}k*@return{number}*/varl......