Mr.Gao

访客数量

Verse For Santa ---- CodeForces - 1279B 背诵得礼物

题目: A - Verse For Santa CodeForces - 1279B

题目思路:

刚拿到这道题时, 解题思路是: 
    首先判断 n 的总和是否小于 s, 若小于s说明圣诞老人给的时间足够我们读完此文章, 若大于则需要我们跳过一段进行读,要求的背诵段落尽量多且顺序。
因为题目要求得到顺序背诵跳过一段求背出的最多段落,最后输出的结果为跳过段落的序号。

01 | 解决方法

我最初的思路:
    若对序列如2,9,1,3,18,1,4进行循环暴力统计, 一定能得出结果, 设跳过第一段在保证圣诞老人听完的前提下能背诵完第二段、第三段此时结果是2,依次跳过第二段、第三段分别能背诵的结果是3,2,每次得出结果后进行比较判断, 若结果大于原结果, 进行最大结果更新, 记录跳跃的段数,最后输出记录的跳跃段数就是结果。
    后来发现我这种写法效率很低, 运行一直超时, 后来又发现了一种好用的方法(参考博客: https://www.cnblogs.com/prjruckyone/p/12781869.html)。

    他的这种思路的关键是设置一个max_para的值用来存储已背诵的最长段落的长度, skip用来存储此最大长度段落的位置, 对序列进行累加, 当背诵总数量超出s时, 跳过skip段落的长度
不读, 再进行累加,若再超出即背诵段落已最多, 输出 skip+1(注意: skip为数组下标, 需结果加1), 简单高效。

Java方式实现的原码

import java.util.Scanner;
public class VerseForSanta {

    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        int examples = sc.nextInt();

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

            int n = sc.nextInt();
            int s = sc.nextInt();
            int[] ns = new int[n];

            for (int j = 0; j < ns.length; j++) {
                ns[j] = sc.nextInt();
            }

            System.out.println(getCount(n, s, ns));
        }
    }

    //定义对每组数据进行计算的方法
    public static int getCount(int n, int s, int[] count) {
        if(isFull(count, s)) return 0;          //调用判断n的和是否大于s的方法, 若大于说明够读,返回0

        int sum = 0;                            //定义sum记录n的和, 初始化为 0
        int max_para = -1;                      //定义最大段落的长度,并时刻更新
        int skip = 0;                           //定义待跳过的段落, 它始终为已读段落的最大值
        boolean flag = false;                   //定义标志域, flag = false表示可以跳过, 否则不能

        for(int i = 0; i < count.length; i++){
            sum += count[i];                    //段落累加
            if(sum > s){                        //若段落大于总时间
                if(flag) break;                 //已不能跳过则break;
                sum -= max_para;                //否则说明可以跳过, 减去已读段落的最大值
                flag = true;                    //跳跃标志置为true
            }
            if(count[i] > max_para){            //若此时段落大于已读最大段落
                max_para = count[i];            //将最大对段落记录
                skip = i;                       //记录最大段落, 作为跳过段落
            }
        }
        return  skip+1;                         //返回数组的下标+1即跳过序号
    }

    //求背诵完整篇文章所需要的秒数
    public static boolean isFull(int[] count, int s){
        int sum = 0;
        for(int i:count){
            sum += i;
            if(sum > s) return false;
        }
        return true;
    }
}

后记

欢迎有疑问的朋友一起沟通交流, 加油! 
posted @ 2020-04-27 16:10  gaoliwei1102  阅读(158)  评论(1编辑  收藏  举报