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
首先,我这道题目是用的记忆化搜索(上一篇文章就是记忆化搜索的入门题,有助于理解)去求对角的和,棋盘上每个格子有四个方向可以遍历,那么我们开一个dp【2005】【2005】【4】的数组来存记忆化这一步,否则每次都要跑上下左右一共2N个数据,复杂度达到了2N^3,瞬间爆炸boom。然后就是XJB算,最后求出答案这一步很关键(但是感觉一开始是数据太水了所以水过去了)。借用别人的解法大概就是,首先我们要保证所取的两个点向四周攻击没有重复的部分,也就是他们x1+y1-x2-y2不可以被2整除。那么我们开一个一维数组,有四个元素,例如我的,ans里面前面两个分别是i + j为偶数时候的坐标(x,y),后面两个是i + j为奇数时候的坐标(x,y)。然后找出他们之和偶数里面最大的,找出奇数里面最大的,输出,即可。(咦,这样分析我一开始的xjb搞的代码也是对的啊!不错不错O(∩_∩)O哈哈~)。
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2005;
LL n, dp[maxn][maxn][4], G[maxn][maxn], G2[maxn][maxn];
int dir[][2] = {1,1,-1,1,-1,-1,1,-1};
struct node
{
int x, y;
LL cnt;
}board[4000005];
bool cmp(node a, node b)
{
return a.cnt > b.cnt;
}
bool check_state(int x, int y){
if(x >= 0 && x < n && y >= 0 && y < n)
return 1;
return 0;
}
LL dfs(int x, int y, int director)
{
LL sum = 0;
if(dp[x][y][director])
return dp[x][y][director];
int nx, ny;
nx = x + dir[director][0];
ny = y + dir[director][1];
if(check_state(nx, ny))
sum += dfs(nx, ny, director);
dp[x][y][director] = sum + G[x][y];
return dp[x][y][director];
}
LL work(int x, int y)
{
int nx, ny;
LL sum;
for(int i = 0; i < 4; i++)
{
sum = 0;
nx = x + dir[i][0];
ny = y + dir[i][1];
if(check_state(nx, ny))
sum += dfs(nx, ny, i);
dp[x][y][i] = sum + G[x][y];
}
sum = 0;
for(int i = 0; i < 4; i++)
sum += dp[x][y][i];
sum -= G[x][y] * 3;
G2[x][y] = sum;
return sum;
}
int main()
{
int k = 0;
cin >> n;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
scanf("%d", &G[i][j]);
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
// board[k].x = i + 1;
// board[k].y = j + 1;
// board[k++].cnt = work(i, j);
work(i, j);
}
// sort(board, board + k, cmp);
// for(int i = 1; i < k; i++)
// {
// if((board[0].x + board[0].y - board[i].x - board[i].y) % 2 != 0)
// {
// cout << board[0].cnt + board[i].cnt << endl;
// cout << board[0].x << " " << board[0].y << " " << board[i].x << " " << board[i].y << endl;
// break;
// }
// }
int ans[] = {0,0,0,1};
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
if( (i + j) & 1 )//ji
{
if(G2[i][j] > G2[ans[2]][ans[3]])
{
ans[2] = i;
ans[3] = j;
}
}
else
{
if(G2[i][j] > G2[ans[0]][ans[1]])
{
ans[0] = i;
ans[1] = j;
}
}
}
cout << G2[ans[0]][ans[1]] + G2[ans[2]][ans[3]] << endl;
cout << ans[0] + 1 << " " << ans[1] + 1 << " " << ans[2] + 1 << " " << ans[3] + 1 << endl;
return 0;
}