其他分享
首页 > 其他分享> > [DP] Jzoj P3198 蚂蚁寻路

[DP] Jzoj P3198 蚂蚁寻路

作者:互联网

Description

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

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

Input

在输入文件ant.in 中,第一行三个数n,m,k。意义如题目描述。
接下来一个n 行m 列的整数矩阵,表示棋盘。

Output

在输出文件ant.out 中,一个数,表示蚂蚁所走路径围出的图形可能的最大权值和。
 

Sample Input

2 5 2
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1

Sample Output

-8
 

Data Constraint


10%的数据所有格子中权值均非负
另20%的数据n=2
另30%的数据k=0
100%的数据1≤n≤100,1≤m≤100,0≤k≤10 保证存在合法路径,数据有梯度,格子中每个元素的值绝对值不超过10000
 

Hint

除了第一行的第二个和第一行的第四个都要围起来才至少合法。

 

题解

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 using namespace std;
 5 const int N=210,inf=1e9;
 6 int n,m,k,a[N][N],s[N][N],f[N][N][N],g[N][N][N][3],ans=-inf;
 7 int main()
 8 {
 9     scanf("%d%d%d",&n,&m,&k),k=k*2+1;
10     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) scanf("%d",&a[i][j]),s[i][j]=s[i-1][j]+a[i][j];
11     for (int i=1;i<=k;i++) for (int j=1;j<=n;j++) f[0][i][j]=g[0][i][j][0]=g[0][i][j][1]=-inf;
12     for (int i=1;i<=n;i++)
13         for (int j=1;j<=m;j++)
14         {
15             for (int p=1;p<=k;p++)
16             {
17                 for (int q=i;q>=1;q--) f[j][p][q]=max(f[j-1][p][q],g[j-1][p-1][q][p%2])+s[i][j]-s[q-1][j];
18                 g[j][p][1][0]=-inf;
19                 for (int q=2;q<=i;q++) g[j][p][q][0]=max(g[j][p][q-1][0],f[j][p][q-1]);
20                 g[j][p][i][1]=-inf;
21                 for (int q=i-1;q>=1;q--) g[j][p][q][1]=max(g[j][p][q+1][1],f[j][p][q+1]);
22             }
23             ans=max(ans,max(f[j][k][i],g[j][k][i][0]));
24         }
25     printf("%d",ans);
26 }

 

标签:蚂蚁,Jzoj,int,max,矩阵,P3198,右转,左转,DP
来源: https://www.cnblogs.com/Comfortable/p/10335903.html