您的位置:首页 > 其它

cf Croc Champ 2012 - Round 1 C. Spiral Maximum

2014-07-04 22:23 489 查看
C. Spiral Maximum

time limit per test
3 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

Let's consider a k × k square, divided into unit squares. Please note that
k ≥ 3 and is odd. We'll paint squares starting from the upper left square in the following order: first we move to the right, then down, then to the left, then up, then to the right again and so on. We finish moving in
some direction in one of two cases: either we've reached the square's border or the square following after the next square is already painted. We finish painting at the moment when we cannot move in any direction and paint a square. The figure that consists
of the painted squares is a spiral.


The figure shows examples of spirals for
k = 3, 5, 7, 9.
You have an n × m table, each of its cells contains a number. Let's consider all possible spirals, formed by the table cells. It means that we consider all spirals of any size that don't go beyond the borders
of the table. Let's find the sum of the numbers of the cells that form the spiral. You have to find the maximum of those values among all spirals.

Input
The first line contains two integers n and
m (3 ≤ n, m ≤ 500) — the sizes of the table.

Each of the next n lines contains
m space-separated integers: the j-th number in the
i-th line aij ( - 1000 ≤ aij ≤ 1000) is the number recorded
in the j-th cell of the
i-th row of the table.

Output
Print a single number — the maximum sum of numbers among all spirals.

Sample test(s)

Input
6 5
0 0 0 0 0
1 1 1 1 1
0 0 0 0 1
1 1 1 0 1
1 0 0 0 1
1 1 1 1 1


Output
17


Input
3 3
1 1 1
1 0 0
1 1 1


Output
6


Input
6 6
-3 2 0 1 5 -1
4 -1 2 -3 0 1
-5 1 2 4 1 -2
0 -2 1 3 -1 2
3 1 4 -3 -2 0
-1 2 -1 3 1 2


Output
13


Note
In the first sample the spiral with maximum sum will cover all 1's of the table.

In the second sample the spiral may cover only six 1's.

题意:

在一个n*m的地图中找一个k*k(k为≥3的奇数)的区域,从左上角区域出发,按右、下、左、上的顺序走,当下一个点为边界或者下下个点已经走过就改变方向(如图黑色部分),找一条这样的路径使得所经过的区域路径最大。

思路:

枚举起点,枚举k,O(1)的时间算所经过的路径之和,观察规律可知路径是一圈一圈的,

dp[k][i][j]表示起点为i,j,边长为k时的路径之和,那么dp[k][i][j]=dp[k-4][i+2][j+2]+最外圈的和减去一个点加上一个点。

可以不用存下来,算出i,j后,将起点上移,充分发挥它的作用就行。

比赛时我存下来按照边长的顺序递推出来的,将奇数压缩,开着三维数组过去的,有点衰~

代码:(比赛时代码,有点挫)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define maxn 502
#define MAXN 100005
#define mod 100000000
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;

int n,m,ans;
int a[maxn][maxn],sum[maxn][maxn];
int dp[maxn][maxn][206];

int cal1(int x,int y,int k)
{
return sum[x+k-1][y+k-1]-sum[x-1][y+k-1]-sum[x+k-1][y-1]+sum[x-1][y-1];
}
int cal(int x,int y,int k)
{
int t;
t=cal1(x,y,k)-cal1(x+1,y+1,k-2);
return t;
}
int main()
{
int i,j,t,k,p,sx,sy,ex,ey;
while(~scanf("%d%d",&n,&m))
{
for(i=1; i<=n; i++)
{
for(j=1; j<=m; j++)
{
scanf("%d",&a[i][j]);
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
}
}
ans=-INF;
int best,edge;
for(i=1; i<=n; i++)
{
for(j=1; j<=m; j++)
{
dp[i][j][0]=a[i][j];
k=3;
if(i+k-1>n||j+k-1>m) continue ;
sx=i; sy=j;
ex=i+k/2; ey=j+k/2;
edge=k;
best=0;
while(1)
{
if(edge>3) best+=cal(sx,sy,edge)-a[sx+1][sy]+a[sx+2][sy+1];
else if(edge==3) best+=cal(sx,sy,edge)-a[sx+1][sy];
else best+=a[sx][sy];
sx+=2;
sy+=2;
if(sx>ex&&sy>ey) break ;
edge-=4;
}
dp[i][j][1]=best;
ans=max(ans,best);
}
}
int mi=min(n,m);
for(k=5; k<=mi; k+=2)
{
for(i=1; i<=n; i++)
{
for(j=1; j<=m; j++)
{
if(i+k-1>n||j+k-1>m) continue ;
dp[i][j][k/2]=cal(i,j,k)-a[i+1][j]+a[i+2][j+1]+dp[i+2][j+2][(k-4)/2];
ans=max(ans,dp[i][j][k/2]);
}
}
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: