Gargari is jealous that his friend Caisa won the game from the previous problem. He wants to prove that he is a genius.
He has a n × n chessboard. Each cell of the chessboard has a number written on it. Gargari wants to place two bishops on the chessboard in such a way that there is no cell that is attacked by both of them. Consider a cell with number x written on it, if this cell is attacked by one of the bishops Gargari will get x dollars for it. Tell Gargari, how to place bishops on the chessboard to get maximum amount of money.
We assume a cell is attacked by a bishop, if the cell is located on the same diagonal with the bishop (the cell, where the bishop is, also considered attacked by it).
The first line contains a single integer n (2 ≤ n ≤ 2000). Each of the next n lines contains n integers aij (0 ≤ aij ≤ 109)— description of the chessboard.
On the first line print the maximal number of dollars Gargari will get. On the next line print four integers: x1, y1, x2, y2 (1 ≤ x1, y1, x2, y2 ≤ n), where xi is the number of the row where the i-th bishop should be placed, yi is the number of the column where the i-th bishop should be placed. Consider rows are numbered from 1 to n from top to bottom, and columns are numbered from 1 to n from left to right.
If there are several optimal solutions, you can print any of them.
4
1 1 1 1
2 1 1 0
1 1 1 0
1 0 0 1
12
2 2 3 2
题目大意:
给出一个n*n的棋盘,每个格子拥有a[i][j]美元,现在有两个“大主教”棋子,任意一个棋子均可以攻击两个对角线上的所有格子并可获得格子里的美元。
要求求出可获得最多的钱,并且要求每个格子不能都受到两个棋子的攻击。
解法:
这里主要考对n阶行列式的一些基本性质:
1. 主对角线 l[k] = sum(a[i][j]) 其中i+j = k; 所以k的范围是 2 ~ 2*n
2. 副对角线 r[k] = sum(a[i][j]) 其中i-j = k; 所以k的范围是 1-n ~ 1+n
3. i+j为奇数的格子的对角线 与 i+j为偶数的格子的对角线永不相交, 反之,奇偶性相同的则必然相交。
掌握了这些性质,就构造出本题的解法:
首先算出每条对角线的值,主对角线为l[k],副对角线为r[k];枚举每一个格子,找出i+j为偶数符合条件的格子,找出i+j为奇数符合条件的格子。
注意:和可能为0, 所以在设置最小值的时候应该为-1;
代码:
#include <iostream>
#include <cstdio>
#define N_max 2010
#define LL long long
using namespace std;
int n;
LL l[2*N_max], r[2*N_max], a[N_max][N_max];
LL oddn, oddi, oddj, evenn, eveni, evenj;
void init() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
scanf("%I64d", &a[i][j]);
l[i+j] += a[i][j];
r[i-j+n] += a[i][j];
}
}
void solve() {
oddn = -1;
evenn = -1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if ((i+j)%2) {
if (l[i+j] + r[i-j+n] - a[i][j] > oddn) {
oddn = l[i+j] + r[i-j+n] - a[i][j];
oddi = i;
oddj= j;
}
}
else{
if (l[i+j] + r[i-j+n] - a[i][j] > evenn) {
evenn = l[i+j] + r[i-j+n] - a[i][j];
eveni = i;
evenj = j;
}
}
cout << evenn+oddn << endl;
cout << oddi << ' ' << oddj << ' ' << eveni << ' ' << evenj << endl;
}
int main() {
init();
solve();
}