Hduacm1003 Max Sum

http://acm.hdu.edu.cn/showproblem.php?pid=1003  Max Sum,
求解最大字段和问题,刚开始做这道题时没接触什么算法,就直接穷举每个字段和,复杂度是O(n^3), 毫无疑问超时了, 优化后,缩小到了O(n^2), 但是测试数据量太大,又超时了。
 

  
  
  
  
  1. ////O(n^3) 枚举法   
  2. for(max = -100000, i=1; i<=n; ++i)  
  3.   for(j=1; j<=n; ++j){  
  4.       sum = 0;  
  5.      for(k=i; k<=j; ++k)  
  6.       sum += a[k];  
  7.       if(sum>max){//要求找第一个最大子序列   
  8.          max = sum;  
  9.          l = i;  
  10.          r = j;  
  11.       }  
  12.  }    
  13. /////O(n^2) 枚举法  
  14. for(max = -100000, i=1; i<=n; ++i)  
  15.   for(sum=0, j=i; j<=n; ++j){  
  16.      sum +=  a[j];  
  17.      if(sum>max){  
  18.        max = sum;  
  19.        l = i;  
  20.        r = j;  
  21.      }  
  22.   } 

上网了解了一下DP问题的解法,顺便就练练手,
 

  
  
  
  
  1. #include<iostream>  
  2. #include<memory>  
  3. //#include<fstream>  
  4. #define MaxNum 100010  
  5. using namespace std;  
  6. int T;  
  7. int N;   
  8. int a[MaxNum];  
  9. int main()  
  10. {  
  11.     //ifstream infile("data.txt");  
  12.     cin>>T;//infile>>T;  
  13.     for(int n=1; n<=T; ++n){  
  14.        cin>>N;  
  15.        memset(a, 0, sizeof(a));  
  16.        for(int i=1; i<=N; ++i){  
  17.          cin>>a[i];  
  18.        }  
  19.        int sum = a[1];  
  20.        int b   = a[1];  
  21.        int beg = 1, end = 1;  
  22.        int TmpIter1 = beg, TmpIter2 = end;  
  23.        for(int i=2; i<=N; ++i){  
  24.           if(b >= 0){  
  25.             b += a[i];  
  26.             TmpIter2 = i;  
  27.             //TmpIter1 = beg;  
  28.           }   
  29.           else{  
  30.             b = a[i];  
  31.             TmpIter1 = i;  
  32.             TmpIter2 = i;  
  33.             //beg = i;  
  34.           }  
  35.             
  36.           if(sum < b){///////****QUESTION******/////   
  37.             sum = b;  
  38.             beg = TmpIter1;  
  39.             end = TmpIter2;  
  40.           }  
  41.             
  42.        }  
  43.        cout<<"Case "<<n<<":"<<endl;  
  44.        cout<<sum<<" "<<beg<<" "<<end<<endl;  
  45.        if(n!=T)  
  46.          cout<<endl;  
  47.     }   
  48.     //system("pause");  
  49.     return 0;  

结果怎么提交都会WA,想了很多种测试实例,都没有出错, 无意间,改了代码(36行)sum<b 为 sum<=b,
这明显会出错,因为题中要求打印出第一个最大字段和的区间, 例如:5 1 0 0 0 0 0的第一个最大
字段和的区间是1 1;但是更改后,会输出1 5,但是提交竟然会AC,见鬼了!
看看别人提交的程序,我更改了一小部分,但是精髓不变,

 

  
  
  
  
  1. #include<stdio.h>  
  2. #include<string.h>  
  3. #include<stdlib.h>  
  4. #include<iostream>  
  5. using namespace std;  
  6. int main()  
  7. {  
  8.  
  9.     int r = 0,l = 0,i= 0 ,j = 0,num = 0,n;// l用来记录最大左范围r 右  
  10.     int *a;//,[6]={5,6,5,-4,-7,3};  
  11.     int sum = 0,max = 0,t= 1;  
  12.     //ifstream infile("data.txt");  
  13.     cin>>n;//infile>>n;  
  14.     while(n--)  
  15.     {  
  16.         cin>>num;  
  17.         a = (int *)calloc(num,sizeof(int));  
  18.         for(i = 0; i < num ;i ++)  
  19.             cin>>a[i];  
  20.               
  21.         for( l = 0,r = 0,sum = 0,max = a[0],i = 0;i <num ;i ++)  
  22.         {  
  23.             for(sum = 0,j = i ;j < num ;j ++)  
  24.             {  
  25.                 sum += a[j];  
  26.                 if(sum > max)  
  27.                 {  
  28.                     max = sum;  
  29.                     l = i;  
  30.                     r = j;  
  31.                 }////删除这个判断语句将会导致超时   
  32.                 if(sum < 0){  
  33.                   i = j;///******举个例子:逻辑上更清晰一些: a b c d e f g h i j k l m n   
  34.                   sum = 0;////////////////////************//   sum=(b+c+d)<0;   
  35.                   break;////////////////////////////*****//以e为起点的子序列必大于以b为起点的子序列   
  36.                 }////////////////////////////////////*****还有必要搜索以b为起点的最大子序列吗????   
  37.             }  
  38.         }  
  39.         printf("Case %d:\n%d %d %d\n",t++,max ,l+1 ,r+1);  
  40.         if( n)  
  41.             printf("\n");  
  42.     }  
  43.     //system("pause");  
  44.     return 0;  

但是,我再次更改了代码后,还是提交AC的,即:将(26)sum > max 改为sum>=max。
这时Sample中的 7 0 6 -1 1 -6 7 -5 会输出第一个最大字段和的区间为6 6。为何AC???除了系统测试有问题还有更好的解释吗??????

你可能感兴趣的:(职场,休闲,Hduacm1003,DP问题)