您的位置:首页 > 其它

UVa 10827 Maximum sum on a torus 解题报告(前缀和)

2014-07-19 13:02 477 查看
Problem H

Maximum sum on a torus

Input:
Standard Input
Output: Standard Output
 

Agrid that wraps both horizontally and vertically is called a torus. Given atorus where each cell contains an integer, determine the sub-rectangle with thelargest sum. The sum of a sub-rectangle is the sum of all the elements in thatrectangle. The grid below
shows a torus where the maximum sub-rectangle hasbeen 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 oftest cases (at most 18). Each case starts with an integer N(1≤N≤75) specifying the size of the torus (always square). Thenfollows N lines describing the torus, each line containing N integers between-100
and 100, inclusive.

 

Output

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

 

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则删除。统计最大值即可。代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <string>
using namespace std;

#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
#define mem(a) memset((a), 0, sizeof(a))
typedef long long LL;
typedef unsigned long long ULL;
void work();

int main()
{
#ifdef ACM
freopen("in.txt", "r", stdin);
// freopen("in.txt", "w", stdout);
#endif // ACM

work();
}

/*****************************************/

struct Node
{
int row, val;
bool operator<(const Node & cmp) const
{
return val > cmp.val;
}
} x;

int num[155][155];

void work()
{
int T;
scanf("%d", &T);
ff(cas, T)
{
int n;
scanf("%d", &n);

fff(i, 1, n) fff(j, 1, n)
{
scanf("%d", &num[i][j]);
num[i+n][j+n] = num[i+n][j] = num[i][j+n] = num[i][j];
}

int n2 = n * 2;
fff(i, 1, n2) fff(j, 1, n2)
num[i][j] += num[i-1][j] + num[i][j-1] - num[i-1][j-1];

int ans = num

;
fff(j2, 1, n2) fff(j1, max(1, j2-n+1), j2)
{
priority_queue<Node> que;
x.row = 0;
x.val = 0;
que.push(x);

fff(i, 1, n2)
{
// 删去不符合条件的最小值
while(que.top().row + n < i)
que.pop();

int sum = num[i][j2] - num[i][j1-1];
ans = max(ans, sum - que.top().val);

// 更新最小值
x.row = i;
x.val = sum;
que.push(x);
}
}

printf("%d\n", ans);
}
}


    速度一般般了,有更快的方法。不过这么写比较方便。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: