题目链接:点击打开链接
给一个带有数值的棋盘,找两个主教的位置,使其攻击值最大,且他们的攻击对象不能为相同的位置。。
主教的攻击位置为其同在的对角线。。
思路:
1.先处理出所有的对角线的值。。
我们可以看出一个棋盘的相同对角线会有特定的值。。其主对角线方向的列表和行标的差为特定值,其副对角线方向的行标和列表的和为特定值。
2.我们可以观察到(其实很难观察到),当两个主教的位置的行标和列表奇偶一样的时候,他们会攻击到相同的位置。。
所以, 我们只需要枚举当行标+列表为奇数和偶数的最大值即可。。。
Code:
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
#define LL long long
const int N = 2005;
const int PY = N - 5;
LL map[N][N];
LL ans1[N * 2], ans2[N * 2];
int main()
{
int n;
memset(ans1, 0, sizeof(ans1));
memset(ans2, 0, sizeof(ans2));
scanf("%d", &n);
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n; j ++){
scanf("%I64d", &map[i][j]);
ans1[i + j] += map[i][j];
ans2[j - i + n] += map[i][j];
}
}
LL evenmax = -1, oddmax = -1, x1, y1, x2, y2;
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n; j ++){
LL k = ans1[i + j] + ans2[j - i + n] - map[i][j];
if((i + j) % 2 && k > oddmax){
oddmax = k;
x1 = i; y1 = j;
}
else if((i + j) % 2 == 0 && k > evenmax){
evenmax = k;
x2 = i; y2 = j;
}
}
}
printf("%I64d\n%I64d %I64d %I64d %I64d\n", evenmax + oddmax, x1, y1, x2, y2);
return 0;
}
cin的速度真是不敢恭维。。。printf才给过。。。