hdu 1003 - Max Sum(分治of贪心)
今天比赛的一道题目,有位同学写的代码比我写的好多了,而且有点贪心的意思,所以就贴了上来,
用sum来存前面的正和,如果sum<0的话,那么sum就置成0,意为前面的和都不要了,而重新开始找最大连续和。
这是因为前面的和小于0的话,对后面的最大连续和,做不了贡献,反而会拖了后腿。
如果现在的sum比max要大的话,则更新答案,
代码如下:
#include <cstdio> #define M 100005 #define INF 0x7fffffff int main () { int t, n, x, start, end, sum, maxx, tt, k = 0; scanf("%d",&t); while(t--) { scanf("%d",&n); start = 1; end = 1; sum = 0; tt = 1; maxx = -INF; for(int i = 1; i <= n; ++i) { scanf("%d",&x); sum+=x; if(sum>maxx) { maxx = sum; end = i; start = tt; } if(sum<0) { sum = 0; tt = i+1; } } if(k) printf("\n"); printf("Case %d:\n%d %d %d\n", ++k, maxx, start, end); } return 0; }
还有就是自己写的分治的代码,很长,而且不好写,,
具体思路就是入门经典上的分治法,每个区间的最大连续和或在【0......m】,或在【m+1....n】,或在【x,....m.....y】;
最后再选出最大的即可。。
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define M 100005 #define INF 0x7fffffff int n, a[M]; long long sum[M]; int solve(int l, int r, int &x, int &y) { if(l==r) { x = l; y = l; return a[l]; } int lx, ly, rx, ry; int m = (l+r)/2; solve(l,m,lx,ly); solve(m+1,r,rx,ry); int Lx = m, Rx = m+1; long long L = -INF, R = -INF; for(int i = m; i >= l; --i) if(sum[m]-sum[i-1]>=L) { L = sum[m]-sum[i-1]; Lx = i; } for(int i = m+1; i <= r; ++i) if(sum[i]-sum[m]>R) { R = sum[i]-sum[m]; Rx = i; } if(sum[ly]-sum[lx-1]>=sum[ry]-sum[rx-1]) { x = lx; y = ly; } else { x = rx; y = ry; } if(L+R > sum[y]-sum[x-1]) { x = Lx; y = Rx; } else if(L+R == sum[y]-sum[x-1]&&Lx < x) { x = Lx; y = Rx; } return sum[y]-sum[x-1]; } int main () { int t, k = 0; scanf("%d",&t); getchar(); while(t--) { scanf("%d",&n); for(int i = 1; i <= n; ++i) { scanf("%d",&a[i]); sum[i] = sum[i-1]+a[i]; } int ansx, ansy; long long maxsum = solve(1,n,ansx,ansy); if(k) printf("\n"); printf("Case %d:\n%I64d %d %d\n",++k,maxsum, ansx, ansy); } return 0; }