HDU1003 MAX SUM

题目大意:经典的最大连续子序列和

思路:本来是今天开始学点DP的,但是就是一些经典DP例子还是要先掌握啊~~不过学长说这道题如果认真的用DP来解释的话算是很难的题目的~~是不是我就很难考证了~~不过我反正知道~~如果不是提前有思路的话~~我相信没几个人会把这道题当做水题~~有了思路~~就水过了~~因为DP的编码一向都是很简洁的~~只不过我的编码能力还是暴虐全场啊~~只不过是被题目虐的那一种啊~~囧。。不过我更多的感觉是自己模拟过的~~囧。。

状态方程 sum[i] = sum[i - 1] > 0 ? sum[i - 1] + a[i] : a[i]    下标做得我很恶心~~编码能力啊~~求给力啊~~

关键思路:tmp:在序列中的求和。   sum:保存MAX。  每次tmp<0的时候就要令其为0,从新开始,在这里设立一个变量保存变动的起点很重要。起点在tmp更新为0的时候就设立为i+1(下一个位置的关系),当然这种设立情况要特殊处理n==1和全部为负数的特殊情况。如果tmp>sum的时候,那么终点指针更新,此时顺便更新起始位置的指针是因为刚开始的时候tmp还没大于sum,但是虽然我的剑掉在河里面了,但是我已经拿了一个竹竿插在那了,此时的更新是我如果知道tmp>sum了的话,就在本子上记上这个最新竹竿。

AC program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define oo -10000000 
using namespace std;
int mm[100005]; 
int main()
{
int test;
cin>>test;
int cas=1; 
while(test--)
{
  if(cas>=2)cout<<endl; 
  int n; 
  memset(mm,0,sizeof(mm)); 
  cin>>n;
  for(int i=0;i<n;i++)
  {
    cin>>mm[i];        
  }
  if(n==1)  //特殊情况一
    { 
      cout<<"Case "<<cas++<<':'<<endl;              //输出感觉很恶心,要不是我开始用cin了,早就scanf printf了。囧
      cout<<mm[0]<<' '<<1<<' '<<1<<endl;
      continue;      
    }
  int tmppp=oo;  
  int tag,kg=0; //特殊情况二
  for(;kg<n;kg++)
     {
         if(mm[kg]>0)
           break;
         if(mm[kg]>tmppp)
          {
               tmppp=mm[kg];
               tag=kg; 
          } 
                  
     }
  if(kg==n)
      {
        cout<<"Case "<<cas++<<':'<<endl;
        cout<<tmppp<<' '<<tag+1<<' '<<tag+1<<endl;
        continue;     
      } 
  int sum=0,tmp=0,ffs=0,fs,fl;         //一般情况   
  for(int i=0;i<n;i++)
  {
     tmp+=mm[i];
     //cout<<"tmp  "<<tmp<<endl; 
     if(tmp<0)// 
         {
            ffs=i+1; //ffs这个变动的起点下标很重要
            tmp=0; 
         } 
     else if(tmp>sum)  //小于0的时候就另外开始,

                                 //对于新的一堆数如果有更大的话,

                                //那么最好的是既保存了以往的开始下标有保存了现在的开始下标

                                //一旦新的一堆更大的时候,就把以往的开始下标更新为现在的开始下标
         {
            sum=tmp;
            fs=ffs; 
            fl=i; 
         }  
  
           
  }
  cout<<"Case "<<cas++<<':'<<endl; 
  cout<<sum<<' '<< fs+1<<' '<<fl+1<<endl;//数组下标加上1得到位置
} 
//system("pause"); 
return 0;} 


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值