UVa:10827 Maximum sum on a torus

一开始试图将原矩阵的上下左右八方向全部复制一遍来模拟这个环,后来发现难以解决最大矩阵长度只能是n的问题。

于是后来想到了现在这个办法用取余来模拟循环,在水平的方向上有两种情况,分别是中间相连的和两边想加的,用前缀和的方法求和,但注意不要加重了。竖直方向上要枚举最优矩阵的边,然后往下累加,超过n的要取余,可以累加的边数目不超过n。这样一共是四重循环。数据量只有75。2.4s水过。。

 

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
int Mat[300][300];
int sum[300][300]= {0};
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        memset(Mat,0,sizeof(Mat));
        memset(sum,0,sizeof(sum));
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
                scanf("%d",&Mat[i][j]);
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
                sum[i][j]=sum[i][j-1]+Mat[i][j];
        int mxn=0;
        for(int i=1; i<=n; ++i)
            for(int ii=i; ii<=n; ++ii)
            {
                int S;
                for(int j=1; j<=n; ++j)
                {
                    S=0;
                    for(int jj=j; jj<j+n; ++jj)
                    {
                        int ss=sum[(jj-1)%n+1][ii]-sum[(jj-1)%n+1][i-1];
                        if(S<0) S=ss;
                        else S+=ss;
                        mxn=max(S,mxn);
                    }
                }
                for(int j=1; j<=n; ++j)
                {
                    S=0;
                    for(int jj=j; jj<j+n; ++jj)
                    {
                        int ss= sum[(jj-1)%n+1][i-1]+sum[(jj-1)%n+1][n]-sum[(jj-1)%n+1][ii-1];
                        if(S<0) S=ss;
                        else S+=ss;
                        mxn=max(S,mxn);
                    }
                }
            }
        printf("%d\n",mxn);
    }
    return 0;
}


 

你可能感兴趣的:(动态规划)