cf Croc Champ 2012 - Round 1 C. Spiral Maximum

来源:互联网 发布:linux下安装pyqt5 编辑:程序博客网 时间:2024/05/14 10:22
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 thatk ≥ 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 fork = 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 andm (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 thei-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 50 0 0 0 01 1 1 1 10 0 0 0 11 1 1 0 11 0 0 0 11 1 1 1 1
Output
17
Input
3 31 1 11 0 01 1 1
Output
6
Input
6 6-3 2 0 1 5 -14 -1 2 -3 0 1-5 1 2 4 1 -20 -2 1 3 -1 23 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-6typedef 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;}




0 0
原创粉丝点击