【最大子区间和】旅游路线(travel.pas/c/cpp)
旅游路线
travel.pas/c/cpp
话说LCINF信息组来到烟台参加夏令营。一天,大家提议出去游玩,来到了烟台最繁华的地方。由于他们对烟台不了解,怕迷了路,所以,他们正焦急的想办法。这时,天上突然现身一个老人(这是 所以,他们正焦急的想办法。这时,天上突然现身一个老人(这是真亊……),对我们说:“这片街道呈网状,其中东西向的街道是旅游街,南北向的街道是绿化道。由于游客众多,旅游街被规定为单行道,只能由西向东走,而绿化道是双向通道,两个方向都能通过,我在所有旅游街相邻两个路口之间打上了分值(-10000到10000之间),而在绿化道均没有打分。你们可以从任何一个位置开始游览,从任何一个位置停止游览,但必须使得所经过分值的和最大。你们只要找到这样一条路径,我便出现带你们离开这里(如图)。”
说完,那位神秘的老人就消失了。信息组的同学们这才恍然大悟,于是就想办法,可是他们已经走了三个小时,还没有喝一口水(苦啊!),他们已经筋疲力尽了。所以这个光荣而艰巨的任务就交给你了。帮助他们渡过难关吧!
输入:
第一行两个整数 m和n,表示 m 条横向街道,n个分值点。
接下来是一个m*n的矩阵。第I行第 第J列的数表示一个分值点。
输出:
一个整数p,表示最大值。
【样例输入】travel.in
3 5
-50 -47 36 -30 -23
17 -19 -34 -13 -8
-42 -3 -43 34 -45
【样例输出】travel.out
84
【数据规模】
对于100%的数据
1<=n<=5000
1<=a<=b<=2^63
这一题考试的时候想用动规做来着,但是没做出来,就改成了深搜,全部超时(杯具啊。。。)
当然动规可以解决问题,不过后来经过同学提示发现了贪心很简单!
由于只能向右走,当然向上向下也可以所以总体方向是向右的,并且竖着走是不取值的,而且可以来回随便走,所以我们就可以确定每一次必定选每一列最大的走。所以我们读数据的时候就可以处理一下,只读每一列最大的那个。最后就成了一行数据,题目中说从任意点出发到任意点结束,我们现在就转化成了求刚才得到的一行数据中最大子区间和
C++ Code
/* C++ Code http://oijzh.cnblogs.com */ #include<cstdio> #include<algorithm> using namespace std; #define MAXM 3010 #define INF 0x77777777 int n,m,a[MAXM],sum[MAXM]; int main() { freopen("travel.in","r",stdin); freopen("travel.out","w",stdout); scanf("%d%d",&n,&m); int i,j,x; for(i=1;i<=m;i++)a[i]=-INF; for(i=1;i<=n;i++) for(j=1;j<=m;j++) { scanf("%d",&x); a[j]>?=x; } for(i=1;i<=m;i++)sum[i]=sum[i-1]+a[i]; int maxx=-INF; for(i=1;i<=m;i++) for(j=i;j<=m;j++) maxx>?=sum[j]-sum[i-1]; printf("%d",maxx); return 0; }