【JAVA】每类各选一个后求最大最小值差值的最小值(Pro20210802)(优先级队列 / IndexTree)

本文介绍了如何帮助Lin计算在不同建造方法下,N个便利设施的最大最小值差值的最小值问题。利用优先级队列和索引树的算法思路,解决大规模数据的高效计算,给出具体代码实现。
摘要由CSDN通过智能技术生成

【JAVA】每类各选一个后求最大最小值差值的最小值(Pro20210802)(优先级队列 / IndexTree

题目:

Lin 打算在自己住的村子里建 N 个不同的便利设施。每个便利设施有 K 种建造方法,设施的便利性因建造方法而异。因此,Lin 尝试从 K 种方法中各选择一种来建造这 N 个便利设施。
当 N 个便利设施中便利性最高和最低的差值越小,便利设施越便于使用。Lin 希望算出最小的差值。

[图]

假设便利设施数量 N 为 3,各设施的建造方法数量 K 为 4(如上 [图] 中所示)。如果便利设施 ① 和 ③ 的建成便利性为 1,设施 ② 的便利性为 5,那么上文所述的便利性差值便为 4。如果便利设施 ① 建成便利性为 15,设施 ② 便利性为 17,设施 ③ 便利性为 18,则差值为 3,这是差值最小的情况。

请帮助 Lin 算出上述的最小差值。

[限制条件]

  1. 便利设施数量 N 和建造方法数量 K 均为介于 2 到 100,000 之间的整数。
  2. N * K 不得超过 1,000,000。
  3. 各设施的便利性值为介于 1 到 1,000,000,000 之间的整数。
  4. 同一便利设施的建造方法(便利性值)不会重复。

[输入]
首先,给定测试用例数量 T,后面接着输入 T 种测试用例。在每个测试用例的第一行,给定便利设施类型数量 N 和建造方式数量 K,以空格分隔。接下来的 N 行,每行以升序给定 K 个便利性数值,以空格分隔。
[输出]
每个测试用例输出一行。首先,输出 “#x”(x 为测试用例编号,从 1 开始),加一个空格,然后输出文中提到的最小差值。

[输入和输出示例]
(输入)
3
3 4
1 10 15 24
5 8 17 20
1 6 12 18
3 5
1 6 12 26 35
3 9 28 33 35
10 25 29 30 31
3 5
1 20 37 46 1000000000
1 10 30 59 999999992
10 20 28 41 1000000000

(输出)
#1 3
#2 3
#3 8

思路:

暴力求解的话,从最左侧开始,需要计算每一种可能性。
但对于 ASW = MAX - MIN 来说,想要ASW 更小,只有两种操作,即:MAX减小,或MIN增大。
从最左侧开始的话,MAX不可能再减小了,就只能MIN增大。
对于每一行来说,已经是升序的了,那就是对于MIN所在的行,取下一个,再在每行所选的元素中取最大值和最小值。

代码(优先级队列):

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Main {
   
	static int T, N, K, ASW;
	static int[][] DATA; // 原始数据

	public static void main(String[] args) throws Exception {
   
		System.setIn(new FileInputStream("D:\\SW\\TestCase\\sample_input_20210802.txt"));
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

		StringTokenizer st = new StringTokenizer(bf.readLine());
		T = Integer.parseInt(st.nextToken());

		for (int testcase = 1; testcase <= T; testcase++) {
   
			st = new StringTokenizer(bf.readLine());
			N = Integer.parseInt(st.nextToken());
			K = Integer.parseInt(st.nextToken());

			DATA = new int[N][K];
			ASW = Integer.MAX_VALUE;

			// 读取数据
			for (int row 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值