3111: [Zjoi2013]蚂蚁寻路 - BZOJ

题目描述 Description
在一个 n*m 的棋盘上,每个格子有一个权值,初始时,在某个格子的顶点
处一只面朝北的蚂蚁,我们只知道它的行走路线是如何转弯,却不知道每次转弯
前走了多长。蚂蚁转弯是有一定特点的,即它的转弯序列一定是如下的形式:
右转,右转,左转,左转,右转,右转…左转,左转,右转,右转,右转。
即两次右转和两次左转交替出现的形式,最后两次右转(最后两次一定是
右转)后再多加一次右转。我们还知道,蚂蚁不会在同一个位置连续旋转两次,
并且蚂蚁行走的路径除了起点以外,不会到达同一个点多次,它最后一定是回
到起点然后结束自己的行程,而且蚂蚁只会在棋盘格子的顶点处转弯。
设 k为蚂蚁左转的次数除以2,当k=0 时,蚂蚁可能行走的路径如下图
转弯序列为:右转,右转,右转。
当 k=1 时,蚂蚁可能行走的路径如下图

转弯序列为:右转,右转,左转,左转,右转,右转,右转。
现在已知棋盘大小、每个格子的权值以及左转次数/2 的值,问蚂蚁走出
的路径围出的封闭图形,权值之和最大可能是多少。

输入描述 Input Description
在输入文件ant.in 中,第一行三个数n,m,k。意义如题目描述。
接下来一个n 行m 列的整数矩阵,表示棋盘。
输出描述 Output Description
一个数,表示蚂蚁所走路径围出的图形可能的最大权
值和。
样例输入 Sample Input
2 5 2
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1
样例输出 Sample Output
-8
数据范围及提示 Data Size & Hint
【样例说明】
除了第一行的第二个和第一行的第四个都要围起来才至少合法。
【数据规模与约定】
10%的数据所有格子中权值均非负
另20%的数据n=2
另30%的数据k=0
100%的数据1≤n≤100,1≤m≤100,0≤k≤10 保证存在合法路径,数据有梯度,格子中每个元素的值绝对值不超过 10000

 

 

把题目意思稍微变一下,就是然你选出一个像长城一样的图形,包含的权值最大

我们很容易想到五维动归f[i1,j1,i2,j2,k](i1,j1,i2,j2表示第k个矩形的4个坐标值)(这个k是原来的2*k+1,转换了)

但是五维时间空间上都无法承受

通过五维动归转移的时候我们发现转移的限制条件只有4个,分别是k,这个矩形右下角的横坐标和纵坐标,这个矩形的高度

所以空间成功压到四维f[i,j,k,h]

但是按照原来的转移枚举右上角,其实时间还是五维

再仔细想想,我们必须枚举右上角吗

一个矩形其实是可以拆成一个个的长条的

对了,所以动归方程就出来了,还要一个辅助数组f2[i,j-1,k,h]记录可以转移到f[i,j,k,h]的值

f[i,j,k,h]:=max{f[i,j-1,k,h],f2[i,j-1,k,h]}+sum;

最后注意一下初值的设定

其实这个是刚好卡空间过了,可以把f[i,j,k,h]的i去掉循环用数组


 1 var

 2     f:array[0..101,0..25,0..101]of longint;

 3     f2:array[0..101,0..25,0..101]of longint;

 4     sum:array[0..102,0..100]of longint;

 5     n,m,k,ans:longint;

 6 

 7 procedure init;

 8 var

 9     i,j,l,h:longint;

10 begin

11     read(n,m,k);

12     k:=2*k+1;

13     for i:=1 to n do

14       for j:=1 to m do

15         begin

16           read(sum[i,j]);

17           inc(sum[i,j],sum[i-1,j]);

18         end;

19 end;

20 

21 function max(x,y:longint):longint;

22 begin

23     if x>y then exit(x);

24     exit(y);

25 end;

26 

27 procedure work;

28 var

29     i,j,l,h:longint;

30 begin

31     ans:=-maxlongint;

32     for i:=1 to n do

33       begin

34         fillchar(f,sizeof(f),1<<7);

35         fillchar(f2,sizeof(f2),1<<7);

36         for j:=1 to m do

37           for h:=1 to i do

38             f[j,1,h]:=sum[i,j]-sum[h-1,j];

39         for j:=1 to m do

40           for l:=1 to k do

41             if l and 1=1 then

42               begin

43                 for h:=1 to i do

44                   f[j,l,h]:=max(max(f[j-1,l,h],f2[j-1,l-1,h+1])+sum[i,j]-sum[h-1,j],f[j,l,h]);

45                 for h:=1 to i do

46                   f2[j,l,h]:=max(f[j,l,h],f2[j,l,h-1]);

47               end

48             else

49               begin

50                 for h:=1 to i do

51                   f[j,l,h]:=max(max(f[j-1,l,h],f2[j-1,l-1,h-1])+sum[i,j]-sum[h-1,j],f[j,l,h]);

52                 for h:=i downto 1 do

53                   f2[j,l,h]:=max(f[j,l,h],f2[j,l,h+1]);

54               end;

55         for j:=1 to m do

56           for h:=1 to i do

57             ans:=max(ans,f[j,k,h]);

58       end;

59     write(ans);

60 end;

61 

62 begin

63     init;

64     work;

65 end.
View Code

 

你可能感兴趣的:(ZOJ)