4 solutions

  • 4
    @ 2022-2-19 18:10:50

    典型贪心算法 首先每个金蛋是连续的我们只能取连续的金蛋,并且要让连续相加的值最大那么有以下几种情况要进行讨论 1、如果全都是非正数的情况,那么只需要循环找到最大值即可 2、排除第一种情况那么就一定会存在大于0的数,想让结果最大那么就要尽可能多的正数相加注意,所以我选择直接找到序列的第一个正数从序列的第一个正数开始相加,满足贪心算法的思想,之后如果遇到负数又分为两种情况: (1)如果该正数加上之后的负数过后的值仍然大于0那么让他继续加因为负数后面如果还存在正数那么加上之前的值结果可能会增大,如果结果一旦增大了那么立即保存该结果并记录下坐标 (2)如果正数加上之后的负数小于等于0了那么马上停止,重新寻找第一个正数并再进行2过程

    #include<stdio.h>
    #include<stdlib.h> 
    //贪心算法
    //让尽可能多的正数相加 
    int a[1000001];
    struct value{
    	int head;
    	int tail;
        int sum;
        int max;
    };
    struct value val[100000];
    int main(){
    	int n;//金蛋数量 
    	int sum = 0;
    	int flag = 0;
    	int j = 0;
    	int k = 0;//结构体下标 
    	int max_num = 0;
    	int len = 0;
    	int m = 0;
    	scanf("%d",&n); 
    	for(int i=0; i<n; i++){
    	   scanf("%d",&a[i]);
    	   if(a[i]>0)//如果有一个正数则不是全负 
    	   flag = 1; 	
    	}
    	if(!flag){  //全负的情况,如果全负那么最大的奖励则是负的最小值 
    	    max_num = a[0];
    		for(int i=0; i<n; i++){
    			if(a[i] > max_num){
    				max_num = a[i];
    				j = i;
    			}
    		}
    		printf("%d\n",j+1);
    		printf("%d\n",j+1);
    		printf("%d\n",a[j]);
    		return 0;   
    	}
        else{//竟然有正数那么就先找到第一个正数,有正数就绝对不要从负数开始加 
              while(a[j]<=0)//如果前面有负数则找到第一个非负数 
                j += 1;
                val[k].sum = 0;
                val[k].max = 0;
                len++;
                //将第一个大于零的数存入到结果中 
                val[k].sum += a[j];
                val[k].max += a[j];
                val[k].head = j;
                val[k].tail = j;
                //循环遍历之后的数据 
    		  	for(int i=j+1; i<n; i++){
    		  	    val[k].sum += a[i];//让sum去增加 
    				if(val[k].sum > val[k].max){//说明后面一个数是正数 
    				   val[k].max = val[k].sum;
    				   val[k].tail = i;//终止位向后移动 	
    				}
    				//如果sum<max说明后面一位是负数
    				//注意如果后面有负数是有两种情况的
    				//第一种情况就是加上后面的负数后值仍然大于0
    				//那么再加上后面的正数就会增大
    				//第二种情况如果加上后面的负数过后值小于0了就不要再加了 
    				else{ 
    					if(val[k].sum>0){
    					 continue;
    					}
    					else{//如果加了后面的数值小于等于0了那么就重新从后面的第一个为正的数开始 
    					   	while(a[i] <= 0)
    					   	i++;
    					   	k++;
    					   	len++;
    					   	val[k].sum = 0;
    					   	val[k].max = 0;
    					   	val[k].head = i;
    					   	val[k].tail = i;
    					   	val[k].sum += a[i];
    					   	val[k].max += a[i];
    					}
    				}  	
    			}
    	  }
    	  max_num = val[m].max;
    	  for(int i=0; i<len; i++){
    	  	  if(val[i].max>max_num){
    	  	  	  max_num = val[i].max;
    	  	  	  m = i;
    		 }
    	  }
    	  printf("%d\n",val[m].head+1);
    	  printf("%d\n",val[m].tail+1);
    	  printf("%d\n",val[m].max);			
    }
    

    注意,不同情况得到的最大值都需要保存在对应的结构体数组中,之后再循环遍历结构体数组,找出最大值中的最大值以及坐标

    Information

    ID
    77
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    8
    Tags
    # Submissions
    335
    Accepted
    48
    Uploaded By