【最大子区间和】旅游路线(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;
}

 

 

posted @ 2012-10-19 14:55  jiangzh  阅读(513)  评论(0编辑  收藏  举报