列表

详情


NC20510. [ZJOI2013]蚂蚁寻路

描述

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

输入描述

第一行三个数n,m,k。意义如题目描述。
接下来一个n 行m 列的整数矩阵,表示棋盘。

输出描述

一个数,表示蚂蚁所走路径围出的图形可能的最大权值和。

示例1

输入:

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

输出:

-8

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 55ms, 内存消耗: 8184K, 提交时间: 2022-12-30 10:18:10

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=210;
const int inf=1000000000;
int n,m,k;
int a[maxn][maxn],s[maxn][maxn],f[maxn][maxn][maxn],g[maxn][maxn][maxn][3],ans=-inf;
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	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];
	}
	k=k*2+1;
	for(int i=1;i<=k;i++)
	for(int j=1;j<=n;j++)
	f[0][i][j]=g[0][i][j][1]=g[0][i][j][0]=-inf;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			for(int p=1;p<=k;p++)
			{
				for(int h=i;h>=1;h--)
				f[j][p][h]=max(f[j-1][p][h],g[j-1][p-1][h][p%2])+s[i][j]-s[h-1][j];
				g[j][p][1][0]=-inf;
				for(int h=2;h<=i;h++)
				g[j][p][h][0]=max(g[j][p][h-1][0],f[j][p][h-1]);
				g[j][p][i][1]=-inf;
				for(int h=i-1;h>=1;h--)
				g[j][p][h][1]=max(g[j][p][h+1][1],f[j][p][h+1]); 
			}
			ans=max(ans,max(f[j][k][i],g[j][k][i][0]));
		}
	}
	printf("%d\n",ans);
	return 0;
}

上一题