网易编程题 塔

本文探讨了一个有趣的问题:如何通过移动立方体来最小化由不同高度塔组成的集合的不稳定值。提出了一个算法,该算法在不超过k次操作的情况下,找到使塔高度差最小化的最优方案。输入包括塔的数量、最大操作次数及各塔初始高度,输出是最小不稳定值、操作次数及具体操作步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小易有一些立方体,每个立方体的边长为1,他用这些立方体搭了一些塔。
现在小易定义:这些塔的不稳定值为它们之中最高的塔与最低的塔的高度差。
小易想让这些塔尽量稳定,所以他进行了如下操作:每次从某座塔上取下一块立方体,并把它放到另一座塔上。
注意,小易不会把立方体放到它原本的那座塔上,因为他认为这样毫无意义。
现在小易想要知道,他进行了不超过k次操作之后,不稳定值最小是多少。

输入描述:
第一行两个数n,k (1 <= n <= 100, 0 <= k <= 1000)表示塔的数量以及最多操作的次数。
第二行n个数,ai(1 <= ai <= 104)表示第i座塔的初始高度。

输出描述:
第一行两个数s, m,表示最小的不稳定值和操作次数(m <= k)
接下来m行,每行两个数x,y表示从第x座塔上取下一块立方体放到第y座塔上。

输入例子1:
3 2
5 8 5

输出例子1:
0 2
2 1
2 3

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

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

        List<int[]> a = new ArrayList<>();
        for(int i = 0; i < n; ++i){
            a.add(new int[]{sc.nextInt(), i + 1});
        }

        Collections.sort(a, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[0] - o2[0];
            }
        });

        List<int[]> mem = new ArrayList<>();
        if(n == 1){
            System.out.printf("%d %d\r\n", 0, 0);
        }else if(n == 2){
            int sub = a.get(1)[0] - a.get(0)[0];
            if(k >= sub){
                System.out.printf("%d %d\r\n", 0, sub);
                for(int i = 0; i < sub; ++i){
                    System.out.printf("%d %d\r\n", a.get(1)[1], a.get(0)[0]);
                }
            }else{
                System.out.printf("%d %d\r\n", (sub - k), k);
                for(int i = 0; i < k; ++i){
                    System.out.printf("%d %d\r\n", a.get(1)[1], a.get(0)[0]);
                }
            }
        }else{
            for(int i = 0; i < k; ++i){
                if(a.get(0)[0] == a.get(a.size() - 1)[0]){
                    break;
                }

                mem.add(new int[]{a.get(a.size() - 1)[1], a.get(0)[1]});

                a.set(0, new int[]{a.get(0)[0] + 1, a.get(0)[1]});
                a.set(a.size() - 1, new int[]{a.get(a.size() - 1)[0] - 1, a.get(a.size() - 1)[1]});

                for(int j = 0; (j + 1) < a.size() && a.get(j)[0] > a.get(j + 1)[0]; ++j){
                    int temp_0 = a.get(j)[0];
                    int temp_1 = a.get(j)[1];
                    a.set(j, a.get(j + 1));
                    a.set(j + 1, new int[]{temp_0, temp_1});
                }

                for(int j = a.size() - 1; (j - 1) >= 0 && a.get(j)[0] < a.get(j - 1)[0]; --j){
                    int temp_0 = a.get(j)[0];
                    int temp_1 = a.get(j)[1];
                    a.set(j, a.get(j - 1));
                    a.set(j - 1, new int[]{temp_0, temp_1});
                }
            }

            int s = a.get(a.size() - 1)[0] - a.get(0)[0];
            int m = mem.size();

            System.out.printf("%d %d\r\n", s, m);
            for(int i = 0; i < m; ++i){
                System.out.printf("%d %d\r\n", mem.get(i)[0], mem.get(i)[1]);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值