美文网首页
08年信息学竞赛第四题——西藏难题( java 实现)

08年信息学竞赛第四题——西藏难题( java 实现)

作者: Artfox丶艺狸 | 来源:发表于2018-07-31 11:16 被阅读0次

[TOC]

一、问题描述

    以前,西藏是农奴社会,每个农奴主都拥有数目众多的农奴,这些农奴的整个生命都是农奴主的,农奴主可以随便处死任意一名农奴。
    解放西藏时,政府为了保持农奴主的利益和西藏的和平,并没有立刻废除农奴制度,倒是一些农奴主没有丝毫地改变旧习惯,打死农奴的情况时有发生。
    这天,一个小农奴主又在为难农奴们了,他把他家每一条耗牛背上都写上了一个个位数字(0--9),然后把任意一些牛排在一起,这样就组成了一个多位数字。
    现在他为难大家的难题是,对于牛组成的这个多位数字,他每次会扔出几颗石头,扔出几颗石头就表示需要农奴们从那排牛中赶走多少头牛,这样剩下的牛不改变顺序又组成了一个新的数字,他的要求是,这个新的数字必须要最小。
    如果大家完成不了他的难题,那么每个农奴都要挨打,要知道他打人可是出了名的,不知道有多少个农奴被他打死了。
    请编写一个程序完成这项任务,然后夺下农奴主手里的皮鞭。

输入格式

N I (N是由牛背上的数字排成的多位数,已经牛的数量最少为2,最多为100,I表示扔出的石头的数量,即要从牛中赶走I头牛)

输出格式

S (赶走I头牛后剩下的牛组成的数字,要求这个新的数字最小)

输入输出样例

输入:
1432 2
输出样例:
12

二、问题分析

    这里简单来说:把 N 条牛上的数字组成一个数组,由于不改变顺序的,因此,牵走 I 条牛后,剩下的数组按顺序组成一个最小的数。
     那么什么样的数字最小呢?在位数相同的情况下,肯定是首位最小的值相对小些,然后第二位也取最小值... 依此类推
那么,比如说:3257296  3,我们第一次找到首位最小值:2,接下来找第二最小值 2 然后是9和6

那么怎么确定每个数的查找范围呢?
以上上面的分析为例:在3257296 里面牵走3头牛,那么剩下的牛的数量是4,我们找首位的时候只能从3257里面找,为什么?因为你在后面找到最小值了,那剩下的牛的数量就不够了。第一次最小值是 2。
第二次:确定了首位是2,是前面一个2,那第二次我们查找的位置就是从2后面的那个数字开始,结束位置是还有剩下3条牛的位置:后面的2,即:572里面找最小值,结果为2
第三次查找的位置是从9开始,留下1条牛,那么只有9能选择
第四次查找位置是从6开始,已经到了结束位置,因此最终结果为 2296

分析图

原始数据 第一次遍历 第二次 第三次 第四次 最终

三、JAVA代码

这里只放出核心代码


    /**
     * @param array 原始数组
     * @param m     剩余的个数,不是删除的个数
     * @return
     */
    private static int[] findMin(int[] array, int m) {

        // 校验
        if (m < 0) {
            throw new RuntimeException("m is invalid:" + m);
        }

        int len = array.length;

        if (m > len) {
            throw new RuntimeException("m is too large:" + m + ", the max m is " + len);
        }

        int[] res = new int[m];

        // 起始位置
        int start = 0;

        // 结束位置,需要减 m 是因为保证留下的数字数量
        int end = len - m;

        for (int i = 0; i < m; i++) {

            // 查找此区间的最小值
            for (int j = start + 1; j <= end; j++) {

                if (array[start] > array[j]) {
                    start = j;
                }
            }

            // 将最小值保存到新数组中
            res[i] = array[start];

            // 开始位置右移
            start++;

            // 结束位置右移,因为取到一个数字后,就可以向后多取一位了
            end++;
        }
        return res;
    }

三、测试

我们使用 3257296 从0测试到最大值
下面是测试代码

    public static void main(String[] args) {

        int[] array = {3, 2, 5, 7, 2, 9, 6};

        // 牵走的牛
        for (int i = 0; i <= array.length; i++) {
            test(array, array.length - i);
        }

    }

    private static void test(int[] arr, int m) {
        int[] res = findMin(arr, m);

        System.out.print("剩余 " + m + ":");
        for (int i : res) {
            System.out.print(i);
        }

        System.out.println();
    }

输出的结果

剩余 7:3257296
剩余 6:257296
剩余 5:25296
剩余 4:2296
剩余 3:226
剩余 2:22
剩余 1:2
剩余 0:

四、总结

总体来说难度还好,就是需要分析清楚里面的逻辑,开始我直接去除里面的最大值,没有考虑位置问题,走了一些弯路。

当然如果有其他更好的办法也可以留言。

相关文章

网友评论

      本文标题:08年信息学竞赛第四题——西藏难题( java 实现)

      本文链接:https://www.haomeiwen.com/subject/ihecvftx.html