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

 

posted @ 2014-03-06 17:01  Randolph87  阅读(722)  评论(0编辑  收藏  举报