http://acm.hdu.edu.cn/showproblem.php?pid=1003 Max Sum,
求解最大字段和问题,刚开始做这道题时没接触什么算法,就直接穷举每个字段和,复杂度是O(n^3), 毫无疑问超时了, 优化后,缩小到了O(n^2), 但是测试数据量太大,又超时了。
- O(n^3) 枚举法
- for(max = -100000, i=1; i<=n; ++i)
- for(j=1; j<=n; ++j){
- sum = 0;
- for(k=i; k<=j; ++k)
- sum += a[k];
- if(sum>max){//要求找第一个最大子序列
- max = sum;
- l = i;
- r = j;
- }
- }
- /O(n^2) 枚举法
- for(max = -100000, i=1; i<=n; ++i)
- for(sum=0, j=i; j<=n; ++j){
- sum += a[j];
- if(sum>max){
- max = sum;
- l = i;
- r = j;
- }
- }
上网了解了一下DP问题的解法,顺便就练练手,
- #include<iostream>
- #include<memory>
- //#include<fstream>
- #define MaxNum 100010
- using namespace std;
- int T;
- int N;
- int a[MaxNum];
- int main()
- {
- //ifstream infile("data.txt");
- cin>>T;//infile>>T;
- for(int n=1; n<=T; ++n){
- cin>>N;
- memset(a, 0, sizeof(a));
- for(int i=1; i<=N; ++i){
- cin>>a[i];
- }
- int sum = a[1];
- int b = a[1];
- int beg = 1, end = 1;
- int TmpIter1 = beg, TmpIter2 = end;
- for(int i=2; i<=N; ++i){
- if(b >= 0){
- b += a[i];
- TmpIter2 = i;
- //TmpIter1 = beg;
- }
- else{
- b = a[i];
- TmpIter1 = i;
- TmpIter2 = i;
- //beg = i;
- }
- if(sum < b){///****QUESTION******/
- sum = b;
- beg = TmpIter1;
- end = TmpIter2;
- }
- }
- cout<<"Case "<<n<<":"<<endl;
- cout<<sum<<" "<<beg<<" "<<end<<endl;
- if(n!=T)
- cout<<endl;
- }
- //system("pause");
- return 0;
- }
结果怎么提交都会WA,想了很多种测试实例,都没有出错, 无意间,改了代码(36行)sum<b 为 sum<=b,
这明显会出错,因为题中要求打印出第一个最大字段和的区间, 例如:5 1 0 0 0 0 0的第一个最大
字段和的区间是1 1;但是更改后,会输出1 5,但是提交竟然会AC,见鬼了!
看看别人提交的程序,我更改了一小部分,但是精髓不变,
- #include<stdio.h>
- #include<string.h>
- #include<stdlib.h>
- #include<iostream>
- using namespace std;
- int main()
- {
- int r = 0,l = 0,i= 0 ,j = 0,num = 0,n;// l用来记录最大左范围r 右
- int *a;//,[6]={5,6,5,-4,-7,3};
- int sum = 0,max = 0,t= 1;
- //ifstream infile("data.txt");
- cin>>n;//infile>>n;
- while(n--)
- {
- cin>>num;
- a = (int *)calloc(num,sizeof(int));
- for(i = 0; i < num ;i ++)
- cin>>a[i];
- for( l = 0,r = 0,sum = 0,max = a[0],i = 0;i <num ;i ++)
- {
- for(sum = 0,j = i ;j < num ;j ++)
- {
- sum += a[j];
- if(sum > max)
- {
- max = sum;
- l = i;
- r = j;
- }删除这个判断语句将会导致超时
- if(sum < 0){
- i = j;///******举个例子:逻辑上更清晰一些: a b c d e f g h i j k l m n
- sum = 0;************// sum=(b+c+d)<0;
- break;*****//以e为起点的子序列必大于以b为起点的子序列
- }*****还有必要搜索以b为起点的最大子序列吗????
- }
- }
- printf("Case %d:\n%d %d %d\n",t++,max ,l+1 ,r+1);
- if( n)
- printf("\n");
- }
- //system("pause");
- return 0;
- }
但是,我再次更改了代码后,还是提交AC的,即:将(26)sum > max 改为sum>=max。
这时Sample中的 7 0 6 -1 1 -6 7 -5 会输出第一个最大字段和的区间为6 6。为何AC???除了系统测试有问题还有更好的解释吗??????
本文出自 “东方快翔” 博客,请务必保留此出处http://hustluy.blog.51cto.com/1792080/466092