最短木板长度

最短木板长度

真题目录: 点击去查看

E 卷 100分题型

题目描述

小明有 n 块木板,第 i ( 1 ≤ i ≤ n ) 块木板长度为 ai。
小明买了一块长度为 m 的木料,这块木料可以切割成任意块,拼接到已有的木板上,用来加长木板。
小明想让最短的模板尽量长。请问小明加长木板后,最短木板的长度可以为多少?

输入描述

输入的第一行包含两个正整数, n ( 1 ≤ n ≤ 10^3 ), m ( 1 ≤ m ≤ 10^6 ),n 表示木板数, m 表示木板长度。
输入的第二行包含 n 个正整数, a1, a2,…an ( 1 ≤ ai ≤ 10^6 )。

输出描述

输出的唯一一行包含一个正整数,表示加长木板后,最短木板的长度最大可以为多少?

用例1

输入

5 3
4 5 3 5 5

输出

5

说明

给第1块木板长度增加1,给第3块木板长度增加2后,这5块木板长度变为[5,5,5,5,5],最短的木板的长度最大为5。

用例2

输入

5 2
4 5 3 5 5

输出

4

说明

给第3块木板长度增加1后,这5块木板长度变为[4,5,4,5,5],剩余木料的长度为1。此时剩余木料无论给哪块木板加长,最短木料的长度都为4。

题解

要想让最短的木板尽可能长,那么我们就要不停地递进式补足最短板。

比如用例输入有5个板:4 5 3 5 5,可用材料m=3,最短的板长度是3,只有一个,那么我们就将他补足到4,此时消耗了一单位长度的材料,m=2,这样的话,只剩下两种长度的板4,5,且4长度有两个,5长度有三个,最短板是长度4.接下来我们应该尽量将最短板4长度的板补足到5长度,而刚好剩余材料m=2,可以将所有4长度的板补足到5长度,此时所有板都是5长度,且材料耗尽。

贪心算法

c++

#include<iostream>
#include<vector>
#include<string>
#include <utility> 
#include <sstream>
#include<map>
#include<algorithm>
using namespace std;

int main() {
    int n,m;
    cin >> n >>m;
    vector<int> ans(n);
    for (int i = 0; i < n; i++) {
        cin >> ans[i];
    }
    
    sort(ans.begin(), ans.end());
    // 贪心算法
    while (m--) {
        int pos = 1;
        for (; pos < n; pos++) {
            if (ans[pos] > ans[pos-1]) {
                break;
            }
        }
        ans[pos-1]++;
    }

    cout << ans[0];
    return 0;
}

// 优化实现
#include<iostream>
#include<vector>
#include<string>
#include <utility> 
#include <sstream>
#include<map>
#include<algorithm>
#include<queue>
using namespace std;


struct Compare {
    bool operator()(const pair<int, int>& a, const pair<int, int>& b) {
        return a.first > b.first; // first 值越大优先级越低
    }
};


int main() {
    int n,m;
    cin >> n >>m;
    vector<int> ans(n);
    map<int,int> mp;
    for (int i = 0; i < n; i++) {
        cin >> ans[i];
        mp[ans[i]]++;
    }
    
    // 小顶堆
    priority_queue<pair<int, int>, vector<pair<int, int>>, Compare> pq;
    for (auto p : mp) {
        pq.push({p.first, p.second});
    }
    while (m != 0) {
        pair<int,int> top = pq.top();
        // 都是同样长度,平均分
        if (pq.size() == 1) {
            int count = top.second;
            int num = top.first;
            // 会自定向下取整的
            int diff = m / count;
            pq.pop();
            pq.push({num+diff, count});
            break;
        } else {
            pq.pop();
            pair<int,int> se = pq.top();
            int diff = se.first - top.first;
            int count = top.second;
            
            if (diff * count <= m) {
                pq.pop();
                // 将值提升至se.fisrt消耗的长度
                pq.push({se.first, count + se.second});
                m -= diff * count;
            } else {
                // 这是数量写多少都不影响答案
                pq.push({top.first + (m / count), 1});
                break;
            }
        }
    }
    cout << pq.top().first;
}

JAVA

import java.util.HashMap;
import java.util.PriorityQueue;
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    int n = sc.nextInt();
    int m = sc.nextInt();

    int[] a = new int[n];
    for (int i = 0; i < n; i++) {
      a[i] = sc.nextInt();
    }

    System.out.println(getResult(m, a));
  }

  public static int getResult(int m, int[] a) {
    // 统计每种长度板的数量,记录到woods中,key是板长度,val是板数量
    HashMap<Integer, Integer> woods = new HashMap<>();
    for (Integer ai : a) {
      if (woods.containsKey(ai)) {
        Integer val = woods.get(ai);
        woods.put(ai, ++val);
      } else {
        woods.put(ai, 1);
      }
    }

    // 将统计到的板,按板长度排优先级,长度越短优先级越高,这里使用优先队列来实现优先级
    PriorityQueue<Integer[]> pq = new PriorityQueue<>((b, c) -> b[0] - c[0]);
    for (Integer wood : woods.keySet()) {
      pq.offer(new Integer[] {wood, woods.get(wood)});
    }

    // 只要还有剩余的m长度,就将他补到最短板上
    while (m > 0) {
      // 如果只有一种板长度,那么就尝试将m平均分配到各个板上
      if (pq.size() == 1) {
        Integer[] info = pq.poll();
        int len = info[0];
        int count = info[1];
        return len + m / count;
      }

      // 如果有多种板长度
      // min1是最短板
      Integer[] min1 = pq.poll();
      // min2是第二最短板
      Integer[] min2 = pq.peek();

      // diff是最短板和第二最短板的差距
      int diff = min2[0] - min1[0];
      // 将所有最短板补足到第二短板的长度,所需要总长度total
      int total = diff * min1[1];

      // 如果m的长度不够补足所有最短板,那么说明此时最短板的长度就是题解
      if (total > m) {
        return min1[0] + m / min1[1];
      }
      // 如果m的长度刚好可以补足所有最短板,那么说明最短板可以全部升级到第二短板,且刚好用完m,因此第二短板的长度就是题解
      else if (total == m) {
        return min2[0];
      }
      // 如果m的长度足够长,能补足所有最短板到第二短板,还能有剩余,则将最短的数量加到第二短板的数量上,继续下轮循环
      else {
        m -= total;
        min2[1] += min1[1];
      }
    }

    return pq.peek()[0];
  }
}

Python

# 输入获取
import math

n, m = map(int, input().split())
a = list(map(int, input().split()))


# 算法入口
def getResult(m, a):
    # 统计每种长度板的数量,记录到count中,属性是板长度,属性值是板数量
    count = {}
    for ai in a:
        if count.get(ai) is None:
            count[ai] = 1
        else:
            count[ai] += 1

    # 将统计到的板,按板长度升序
    arr = []
    for ai in count.keys():
        arr.append([int(ai), count[ai]])

    arr.sort(key=lambda x: x[0])

    # 只要还有剩余的m长度,就将他补到最短板上
    while m > 0:
        # 如果只有一种板长度,那么就尝试将m平均分配到各个板上
        if len(arr) == 1:
            lenV, count = arr[0]
            return lenV + math.floor(m / count)

        # 如果有多种板长度
        min1 = arr.pop(0) # min1是最短板
        min2 = arr[0] # min2是第二最短板

        # diff是最短板和第二最短板的差距
        diff = min2[0] - min1[0]

        # 将所有最短板补足到第二短板的长度,所需要总长度total
        total = diff * min1[1]

        # 如果m的长度不够补足所有最短板,那么说明此时最短板的长度就是题解
        if total > m:
            return min1[0] + math.floor(m / min1[1])
        # 如果m的长度刚好可以补足所有最短板,那么说明最短板可以全部升级到第二短板,且刚好用完m,因此第二短板的长度就是题解
        elif total == m:
            return min2[0]
        # 如果m的长度足够长,能补足所有最短板到第二短板,还能有剩余,则将最短的数量加到第二短板的数量上,继续下轮循环
        else:
            m -= total
            min2[1] += min1[1]

    return arr[0][0]


# 算法调用
print(getResult(m, a))

JavaScript

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const lines = [];
rl.on("line", (line) => {
  lines.push(line);

  if (lines.length === 2) {
    const [n, m] = lines[0].split(" ").map(Number);
    const a = lines[1].split(" ").map(Number);
    console.log(getResult(m, a));

    lines.length = 0;
  }
});

function getResult(m, a) {
  // 统计每种长度板的数量,记录到count中,属性是板长度,属性值是板数量
  const count = {};
  for (let ai of a) {
    count[ai] ? count[ai]++ : (count[ai] = 1);
  }

  // 将统计到的板,按板长度升序
  const arr = [];
  for (let ai in count) {
    arr.push([ai - 0, count[ai]]);
  }
  arr.sort((a, b) => a[0] - b[0]);

  // 只要还有剩余的m长度,就将他补到最短板上
  while (m > 0) {
    // 如果只有一种板长度,那么就尝试将m平均分配到各个板上
    if (arr.length === 1) {
      const [len, count] = arr[0];
      return len + Math.floor(m / count);
    }

    // 如果有多种板长度
    // min1是最短板
    let min1 = arr.shift();
    // min2是第二最短板
    let min2 = arr[0];

    // diff是最短板和第二最短板的差距
    let diff = min2[0] - min1[0];

    // 将所有最短板补足到第二短板的长度,所需要总长度total
    let total = diff * min1[1];

    // 如果m的长度不够补足所有最短板,那么说明此时最短板的长度就是题解
    if (total > m) {
      return min1[0] + Math.floor(m / min1[1]);
    }
    // 如果m的长度刚好可以补足所有最短板,那么说明最短板可以全部升级到第二短板,且刚好用完m,因此第二短板的长度就是题解
    else if (total === m) {
      return min2[0];
    }
    // 如果m的长度足够长,能补足所有最短板到第二短板,还能有剩余,则将最短的数量加到第二短板的数量上,继续下轮循环
    else {
      m -= total;
      min2[1] += min1[1];
    }
  }

  return arr[0][0];
}

Go

package main

import (
	"fmt"
	"sort"
)

func getResult(m int, a []int) int {
	// 统计木板长度及其数量
	boardCount := make(map[int]int)
	for _, length := range a {
		boardCount[length]++
	}

	// 转换为切片,并按长度排序
	type board struct {
		length int
		count  int
	}

	boards := make([]board, 0, len(boardCount))
	for length, count := range boardCount {
		boards = append(boards, board{length, count})
	}
	sort.Slice(boards, func(i, j int) bool {
		return boards[i].length < boards[j].length
	})

	// 逐步填充最短板
	for i := 0; i < len(boards)-1; i++ {
		cur := boards[i]
		next := boards[i+1]

		// 计算当前木板与下一个木板的长度差距
		diff := next.length - cur.length
		totalCost := diff * cur.count

		if totalCost > m {
			return cur.length + m/cur.count
		}

		m -= totalCost
		boards[i+1].count += cur.count
	}

	// 只剩下一种木板时,平分剩余 m
	return boards[len(boards)-1].length + m/boards[len(boards)-1].count
}

func main() {
	var n, m int
	fmt.Scan(&n, &m)

	a := make([]int, n)
	for i := range a {
		fmt.Scan(&a[i])
	}

	fmt.Println(getResult(m, a))
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/965159.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flink2支持提交StreamGraph到Flink集群

最近研究Flink源码的时候&#xff0c;发现Flink已经支持提交StreamGraph到集群了&#xff0c;替换掉了原来的提交JobGraph。 新增ExecutionPlan接口&#xff0c;将JobGraph和StreamGraph作为实现。 Flink集群Dispatcher也进行了修改&#xff0c;从JobGraph改成了接口Executio…

Unity扩展编辑器使用整理(一)

准备工作 在Unity工程中新建Editor文件夹存放编辑器脚本&#xff0c; Unity中其他的特殊文件夹可以参考官方文档链接&#xff0c;如下&#xff1a; Unity - 手册&#xff1a;保留文件夹名称参考 (unity3d.com) 一、菜单栏扩展 1.增加顶部菜单栏选项 使用MenuItem&#xff…

2025年02月05日Github流行趋势

项目名称&#xff1a;OCRmyPDF 项目地址url&#xff1a;https://github.com/ocrmypdf/OCRmyPDF项目语言&#xff1a;Python历史star数&#xff1a;15872今日star数&#xff1a;157项目维护者&#xff1a;jbarlow83, fritz-hh, apps/dependabot, mawi12345, mara004项目简介&…

ASP.NET Core中间件的概念及基本使用

什么是中间件 中间件是ASP.NET Core的核心组件&#xff0c;MVC框架、响应缓存、身份验证、CORS、Swagger等都是内置中间件。 广义上来讲&#xff1a;Tomcat、WebLogic、Redis、IIS&#xff1b;狭义上来讲&#xff0c;ASP.NET Core中的中间件指ASP.NET Core中的一个组件。中间件…

【狂热算法篇】并查集:探秘图论中的 “连通神器”,解锁动态连通性的神秘力量

嘿&#xff0c;朋友们&#xff01;喜欢这个并查集的讲解吗 记得点个关注哦&#xff0c;让我们一起探索算法的奥秘&#xff0c;别忘了一键三连&#xff0c;你的支持是我最大的动力&#xff01; 欢迎拜访&#xff1a;羑悻的小杀马特.-CSDN博客 本篇主题&#xff1a;深度剖析并查…

Jupyter Lab的使用

Lab与Notebook的区别: Jupyter Lab和Jupyter notebook有什么区别&#xff0c;这里找到一篇博客不过我没细看&#xff0c; Jupyter Lab和Jupyter Notebook的区别 - codersgl - 博客园 使用起来Lab就是一个更齐全、功能更高级的notebook&#xff0c; 启用滚动输出: 有时候一个…

C++【深入 STL--list 之 迭代器与反向迭代器】

接前面的手撕list(上)文章&#xff0c;由于本人对于list的了解再一次加深。本文再次对list进行深入的分析与实现。旨在再一次梳理思路&#xff0c;修炼代码内功。 1、list 基础架构 list底层为双向带头循环链表&#xff0c;问题是如何来搭建这个list类。可以进行下面的考虑&am…

Games104——游戏引擎Gameplay玩法系统:基础AI

这里写目录标题 寻路/导航系统NavigationWalkable AreaWaypoint NetworkGridNavigation Mesh&#xff08;寻路网格&#xff09;Sparse Voxel Octree Path FindingDijkstra Algorithm迪杰斯特拉算法A Star&#xff08;A*算法&#xff09; Path Smoothing Steering系统Crowd Simu…

2024最新版Node.js详细安装教程(含npm配置淘宝最新镜像地址)

一&#xff1a;Node.js安装 浏览器中搜索Nodejs&#xff0c;或直接用网址:Node.js — 在任何地方运行 JavaScript 建议此处下载长期支持版本&#xff08;红框内&#xff09;: 开始下载&#xff0c;完成后打开文件: 进入安装界面&#xff0c;在此处勾选&#xff0c;再点击n…

高效 MyBatis SQL 写法一

高效 MyBatis SQL 写法一 前言 MyBatis 作为一款优秀的持久层框架&#xff0c;极大地简化了数据库操作。 然而&#xff0c;在实际开发中&#xff0c;XML 配置的编写仍然可能显得繁琐。 本文将分享一些 MyBatis 动态 SQL 的优质写法&#xff0c;帮助开发者提升效率并减少错误…

C语言按位取反【~】详解,含原码反码补码的0基础讲解【原码反码补码严格意义上来说属于计算机组成原理的范畴,不过这也是学好编程初级阶段的必修课】

目录 概述【适合0基础看的简要描述】&#xff1a; 上述加粗下划线的内容提取版&#xff1a; 从上述概述中提取的核心知识点&#xff0c;需背诵&#xff1a; 整数【包含整数&#xff0c;负整数和0】的原码反码补码相互转换的过程图示&#xff1a; 过程详细刨析&#xff1a;…

如何安装PHP依赖库 更新2025.2.3

要在PHP项目中安装依赖&#xff0c;首先需要确保你的系统已经安装了Composer。Composer是PHP的依赖管理工具&#xff0c;它允许你声明项目所需的库&#xff0c;并管理它们。以下是如何安装Composer和在PHP项目中安装依赖的步骤&#xff1a; 一. 安装Composer 对于Windows用户…

【通俗易懂说模型】线性回归(附深度学习、机器学习发展史)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;深度学习_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2. …

硬件电路基础

目录 1. 电学基础 1.1 原子 1.2 电压 1.3 电流 1.电流方向&#xff1a; 正极->负极,正电荷定向移动方向为电流方向&#xff0c;与电子定向移动方向相反。 2.电荷&#xff08;这里表示负电荷&#xff09;运动方向&#xff1a; 与电流方向相反 1.4 测电压的时候 2. 地线…

【含文档+PPT+源码】基于Python爬虫二手房价格预测与可视化系统的设计与实现

项目介绍 本课程演示的是一款基于Python爬虫二手房价格预测与可视化系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 带你从零开始部署运行本套系统 该项…

【数据结构】树哈希

目录 一、树的同构1. 定义2. 具体理解(1) 结点对应(2) 孩子相同(3) 递归性质 3. 示例 二、树哈希1.定义2.哈希过程&#xff08;1&#xff09;叶节点哈希&#xff08;2&#xff09;非叶节点哈希&#xff08;3&#xff09;组合哈希值 3.性质&#xff08;1&#xff09; 唯一性 \re…

渗透测试之文件包含漏洞 超详细的文件包含漏洞文章

目录 说明 通常分为两种类型&#xff1a; 本地文件包含 典型的攻击方式1&#xff1a; 影响&#xff1a; 典型的攻击方式2&#xff1a; 包含路径解释&#xff1a; 日志包含漏洞&#xff1a; 操作原理 包含漏洞读取文件 文件包含漏洞远程代码执行漏洞: 远程文件包含…

Mysql:数据库

Mysql 一、数据库概念&#xff1f;二、MySQL架构三、SQL语句分类四、数据库操作4.1 数据库创建4.2 数据库字符集和校验规则4.3 数据库修改4.4 数据库删除4.4 数据库备份和恢复其他 五、表操作5.1 创建表5.2 修改表5.3 删除表 六、表的增删改查6.1 Create(创建):数据新增1&#…

ChatGPT怎么回事?

纯属发现&#xff0c;调侃一下~ 这段时间deepseek不是特别火吗&#xff0c;尤其是它的推理功能&#xff0c;突发奇想&#xff0c;想用deepseek回答一些问题&#xff0c;回答一个问题之后就回复服务器繁忙&#xff08;估计还在被攻击吧~_~&#xff09; 然后就转向了GPT&#xf…

Vue 中如何嵌入可浮动的第三方网页窗口(附Demo)

目录 前言1. 思路Demo2. 实战Demo 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF 1. 思路Demo 以下Demo提供思路参考&#xff0c;需要结合实际自身应用代码 下述URL的链接使用百度替代&#xff01; 方式 1…