旅游路线travel(NDK1636)

 游览路线
  话说LCINF信息组来到烟台参加夏令营。一天,大家提议出去游玩,来到了烟台最繁华的地方。由于他们对烟台不了解,怕迷了路,所以,他们正焦急的想办法。这时,天上突然现身一个老人(这是真亊……),对我们说:“这片街道呈网状,其中东西向的街道是旅游街,南北向的街道是绿化道。由于游客众多,旅游街被规定为单行道,只能由西向东走,而绿化道是双向通道,两个方向都能通过,我在所有旅游街相邻两个路口之间打上了分值(-10000到10000之间),而在绿化道均没有打分。你们可以从任何一个位置开始游览,从任何一个位置停止游览,但必须使得所经过分值的和最大。你们只要找到这样一条路径,我便出现带你们离开这里(如图)。”
  说完,那位神秘的老人就消失了。信息组的同学们这才恍然大悟,于是就想办法,可是他们已经走了三个小时,还没有喝一口水(苦啊!),他们已经筋疲力尽了。所以这个光荣而艰巨的任务就交给你了。帮助他们渡过难关吧!

 

输入:
第一行两个整数m和n,表示m条横向街道,n个分值点。
接下来是一个m*n的矩阵。第I行第J列的数表示一个分值点。

 

输出:
一个整数p,表示最大值。

 

【样例】
输入  
3 5
-50 -47 36 -30 -23
17 -19 -34 -13 -8
-42 -3 -43 34 –45

输出
84

 

【数据规模】
对于30%的数据
   1<=m<=100
   1<=n<=200
对于100%的数据
   1<=m<=3000
   1<=n<=500

 

算法:DP

真是太裸的一道DP题了,这题画的那个图只会误导选手,其实本质来说这道题就是每次只能在每一列中选一个,然后从左到右走,不限制起始位置。
起始就是一个最大连续子序和问题,f[i]=max(f[i-1]+a[i,j],a[i,j]),每一次以i作为列循环一下就求出解来了,注意f[i]的值永远是走完第i列后的最优值。

 

program travel;

const
 maxn=500;
 maxm=3000;

var
 n,m,ans:longint;
 a:array [0..maxm,0..maxn] of longint;
 f:array [0..maxm] of longint;

procedure init;
var
 i,j:longint;
begin
 ans:=-maxlongint;
 readln(n,m);
 for i:=1 to n do
  begin
   for j:=1 to m do read(a[i,j]);
   readln;
  end;
end;

function max(x,y:longint):longint;
begin
 if x>y then exit(x) else exit(y);
end;

procedure main;
var
 i,j,t,maxx:longint;
begin
 t:=-maxlongint;
 for i:=1 to n do if a[i,1]>t then t:=a[i,1];
 f[1]:=t;
 for i:=2 to m do
  begin
   maxx:=-maxlongint;
   for j:=1 to n do
    begin
     f[i]:=max(f[i-1]+a[j,i],a[j,i]);
     maxx:=max(maxx,f[i]);
    end;
   f[i]:=maxx;
   ans:=max(ans,f[i]);
  end;
end;

begin
 assign(input,'travel.in'); reset(input);
 assign(output,'travel.out'); rewrite(output);
 
 init;
 main;
 writeln(ans);
 
 close(input); close(output);
end.

你可能感兴趣的:(ndk,旅游,output,input,算法,任务)