ACM UVa 算法题 #507 - Jill Rides Again的解法

题目的Link在这里:ACM UVa 507 - Jill Rides Again

本质上来说,本题是一个Maximum Interval Sum问题,也就是求最大连续序列。一般的做法需要o(n^2)的时间,其实有一个简单的O(n)复杂度的解法:

从左到右逐步累加,记录每次累加之后的最大值,假如累加值<0,则将累加值清0,重新累加。当这个过程结束之后所记录的最大值就是最大的连续序列的累加值。因为只需要从左到右扫描一次,因此算法的复杂度为O(n)

直观来说,这样做把整个序列分为(A1, n1), (A2, n2)....(Am, nm)的序列。Ak是一串长度为w的序列a(1), a(2), ...a(w)其中a(1)+...+a(p) > 0对于任意0<p<=w。nk则是一个负数并且Ak+nk<0。这样,直观上来说,nk变成了各个序列的边界,每个序列不应该越过边界否则会导致序列的总和变小。因此最大的序列在A1, ... Am中(包括子序列),于是此算法可以得到最大值。

举例:

Seq=1, 2, -4, 9, -4, -7, 1, 4, 5, -2

Sum=1, 3, -1(清0), 9, 5, -2(清0), 1, 5,10, 7

所以最大的连续序列为1, 4, 5,其和为10。

代码如下:

//
// ACMUVaProblem#507
// http://acm.uva.es/p/v5/507.html
//
// Author:ATField
// Email:[email protected]
//

#include
" stdafx.h "

#include
< iostream >
#include
< vector >
#include
< cstdlib >

using namespace std;

int compute_optimal_route( const vector < int > & dist, int m, int & left_pos, int & right_pos)
... {
if(m<=0)return0;

intmax_interval_sum=0;

intcurrent_interval_sum=0;
intmax_left_pos=-1;
intmax_right_pos=-1;
left_pos
=right_pos=m-1;
for(inti=m-1;i>=0;--i)
...{
current_interval_sum
+=dist[i];
if(current_interval_sum<0)
...{
current_interval_sum
=0;
right_pos
=i-1;

continue;
}


if(current_interval_sum>=max_interval_sum)
...{
max_left_pos
=i;
max_right_pos
=right_pos;
max_interval_sum
=current_interval_sum;
}

}


if(max_interval_sum>0)
...{
left_pos
=max_left_pos;
right_pos
=max_right_pos;

return1;
}


return0;
}


int main( int argc, char * argv[])
... {
std::vector
<int>dist;

intn;
cin
>>n;

for(inti=0;i<n;++i)
...{
intm;
cin
>>m;
m
=m-1;

dist.clear();
if(m>=0)
...{
dist.reserve(m);
for(intj=0;j<m;++j)
...{
intdistance;
cin
>>distance;
dist.push_back(distance);
}

}


intleft_pos,right_pos;
if(!compute_optimal_route(dist,m,left_pos,right_pos))
cout
<<"Route"<<i+1<<"hasnoniceparts"<<endl;
else
cout
<<"Thenicestpartofroute"<<i+1<<"isbetweenstops"<<left_pos+1<<"and"<<right_pos+2<<endl;
}


return0;
}


你可能感兴趣的:(算法,J#)