UVA 10827 - Maximum sum on a torus

Maximum sum on a torus

Input: Standard Input

Output: Standard Output

 

A grid that wraps both horizontally and vertically is called a torus. Given a torus where each cell contains an integer, determine the sub-rectangle with the largest sum. The sum of a sub-rectangle is the sum of all the elements in that rectangle. The grid below shows a torus where the maximum sub-rectangle has been shaded.

 

1

-1

0

0

-4

2

3

-2

-3

2

4

1

-1

5

0

3

-2

1

-3

2

-3

2

4

1

-4

Input

The first line in the input contains the number of test cases (at most 18). Each case starts with an integer N (1≤N≤75) specifying the size of the torus (always square). Then follows N lines describing the torus, each line containing N integers between -100 and 100, inclusive.

 

Output

For each test case, output a line containing a single integer: the maximum sum of a sub-rectangle within the torus.

 

Sample Input                                  Output for Sample Input

2 
5 
1 -1 0 0 -4 
2 3 -2 -3 2 
4 1 -1 5 0 
3 -2 1 -3 2 
-3 2 4 1 -4 
3 
1 2 3 
4 5 6 
7 8 9
15 

45


Problem setter: Jimmy Mårdell

Special Thanks: Derek Kisman, Md. Kamruzzaman


题意:给一个n*n的矩阵,矩阵左右连接,上下连接。求所给矩阵的最大(元素和)子矩阵。


思路:把矩阵copy份拼在原矩阵的右,下,右下,得到一个2n*2n的矩阵,然后问题就变成了在这个2n*2n的矩阵中找出一个最大为n*n的最大子矩阵。


#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define FOR(i, s, t) for(int (i)=(s); (i)<(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));

const int maxn = 200;
int A[maxn][maxn];
int sum[maxn][maxn];

int main() {
    int T;

    scanf("%d", &T);
    while(T--) {
        int n;
        scanf("%d", &n);
        for(int i=1; i<=n; i++) {
            for(int j=1; j<=n; j++) {
                scanf("%d", &A[i][j]);
                A[i+n][j] = A[i][j+n] = A[i+n][j+n] = A[i][j];
            }
        }
        memset(sum, 0, sizeof(sum));
        for(int i=1; i<=2*n; i++) {
            for(int j=1; j<=2*n; j++) {
                sum[i][j] = A[i][j] + sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1];
            }
        }
        int ans = 0;
        for(int i=1; i<=2*n; i++) {
            for(int j=1; j<=2*n; j++) {
                for(int ki=1; ki<=n; ki++) if(i >= ki) {
                    for(int kj=1; kj<=n; kj++) if(j >= kj) {
                        int t = sum[i][j];
                        t = t - sum[i-ki][j] - sum[i][j-kj] + sum[i-ki][j-kj];
                        if(t > ans) {
                            ans = t;
                            // printf("%d %d %d %d\n", i-ki+1, j-kj+1, i, j);
                        }
                    }
                }
            }
        }
        printf("%d\n", ans);
    }

    return 0;
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值