瞌睡 (网易笔试题)

题目描述

小易觉得高数课太无聊了,决定睡觉。不过他对课上的一些内容挺感兴趣,所以希望你在老师讲到有趣的部分的时候叫醒他一下。你知道了小易对一堂课每分钟知识点的感兴趣程度,并以分数量化,以及他在这堂课上每分钟是否会睡着,你可以叫醒他一次,这会使得他在接下来的k分钟内保持清醒。你需要选择一种方案最大化小易这堂课听到的知识点分值。

输入

第一行 n, k (1 <= n, k <= 10^5) ,表示这堂课持续多少分钟,以及叫醒小易一次使他能够保持清醒的时间。
第二行 n 个数,a1, a2, ... , an(1 <= ai <= 10^4) 表示小易对每分钟知识点的感兴趣评分。
第三行 n 个数,t1, t2, ... , tn 表示每分钟小易是否清醒, 1表示清醒。

输出

小易这堂课听到的知识点的最大兴趣值

输入样例 1 

6 3
1 3 5 2 5 4
1 1 0 1 0 0

输出样例 1

16                                                                                                                                                                                                    

题意:

 每分钟都会有两个量,一个是小易对这一分钟知识点的感兴趣评分,以及小易是否清醒,输入的k为叫醒小易后他能保持清醒的时间,只能叫醒小易一次,要求得出小易这堂课听到的知识点的最大兴趣值。

方法一:最先想到的就是一个很暴力的方法,先求出小易醒着的的兴趣值总和sum,然后从头开始遍历每一分钟,判断是否清醒,如果为不清醒,那么就遍历接下来k个值,把这k个值未醒着的分值加到前面的sum上,与记录的最大的兴趣值比较并不断更新最大值。但是这个绝对就会超时,确实超时了。

暴力超时代码:

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
	   
		Scanner in=new Scanner(System.in);
		int n=in.nextInt();
		int k=in.nextInt();
		int[] value=new int[n];    //知识点的兴趣值
		int[] wake=new int[n];     //每分钟是否清醒
		for(int i=0;i<n;i++)
			value[i]=in.nextInt();
	    for(int i=0;i<n;i++)
	        wake[i]=in.nextInt();
	    int sum=0;
	    for(int i=0;i<n;i++)
	    {
	    	if(wake[i]==1)sum+=value[i];
	    }
	    int max=sum;
	    for(int i=0;i<n;i++)
	    {
	    	if(wake[i]==0)
	    	{
	    		int m=sum;
	    		for(int j=i;j<Math.min(i+k, n);j++)
	    		{
	    			if(wake[j]==0)m+=value[i];
	    		}
	    		if(m>max)max=m;
	    	}
	    	
	    }
	    System.out.println(max);
	}

}

方法二:可以定义3个数组,长度都为n。leftv数组是表示从左边开始到右清醒时兴趣值的累加和,rightv数组是表示从右边开始到左清醒时兴趣值的累加和,tolv表示从左到右所有兴趣值的累加和。

       然后当我们遍历到为未醒着的位置i时,那么这时的总的兴趣值为3部分之和:leftv[i-1] + rightv[i+k] + (tolv[i+k-1] - tolv[i-1])。最重要的就是考虑边界问题,第一部分的值为第i分钟左边的值,左边界的问题就是要考虑i-1不能小于0,如果小于0,那么左边的和就不是加leftv[i-1]而是加0,第二部分的值就是第i分钟右边得值,右边界的问题就是要考虑i+k要小于n,如果大于n,那么右边得和就不是加rightv[i+k]而是加0,最后一部分就是i与i+k之间的兴趣值的和,tolv[Math.min(i+k-1, n-1)]-(i<1?0:tolv[i-1]),也是需要考虑边界问题。

  可AC的代码:

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {

		Scanner in=new Scanner(System.in);
		int n=in.nextInt();
		int k=in.nextInt();
		int[] value=new int[n];    //知识点的兴趣值
		int[] wake=new int[n];     //每分钟是否清醒
		for(int i=0;i<n;i++)
			value[i]=in.nextInt();
	    for(int i=0;i<n;i++)
	        wake[i]=in.nextInt();
	    int sum=0;
      
	    int[] leftv=new int[n];            //从左边开始统计此分钟之前清醒时所有的兴趣值
	    for(int i=0;i<n;i++){
	    	if(wake[i]==1)sum+=value[i];
	    	leftv[i]=sum;
	    } 
       
	    int[] rightv=new int[n];         //从右边开始统计此分钟之前清醒时所有的兴趣值
	    sum=0;
	    for(int i=n-1;i>=0;i--)
	    {
	    	if(wake[i]==1)sum+=value[i];
	    	rightv[i]=sum;
	    }
      
	    int[] tolv=new int[n];         //记录此分钟之前的清醒和未清醒所有的兴趣值
	    sum=0;
	    for(int i=0;i<n;i++)
	    {
	       sum+=value[i];
	       tolv[i]=sum;
	    }
      
	    if(n==0)                 //如果n为0,结果一定为0
	    {
	    	System.out.println(0); 
	    }
	    else if(k==0)                 //如果K为0,那么结果就是所有清醒时的兴趣值
	    {
	    	System.out.println(leftv[n-1]);
	    }
	    else                         //n不为0,K也不为0
	    {
	    	int res=0;
		    for(int i=0;i<n;i++)
		    {
		    	if(wake[i]==0)
		    	{
		    		int m=0;
		    		if(i-1<0)m+=0;      //考虑左边界的问题,
		    		else m+=leftv[i-1];
		    		if(i+k>=n)m+=0;     //考虑右边界的问题
		    		else m+=rightv[i+k];
		    		m+=tolv[Math.min(i+k-1, n-1)]-(i<1?0:tolv[i-1]);
		    		if(m>res)res=m;
		    	}
		    }
	        System.out.println(res);
	    }
	}

}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值