题目速递:http://codeforces.com/problemset/problem/463/C
题意:在一个n*n矩阵中,每个小方格中都有一个值。记某方格主对角线副对角线经过的所有方格为他的区域。规定在某个小方格放置bishop时,将会收获该方格区域上方格的值的和,这个和记作该方格的收益。现要放置两个bishops,且放置的两个位置的“区域”不可重叠。问如何放置能得到最大收益。
题解:画一下图会发现,同一条主对角线上的点的坐标(x,y),其x-y为定值;同一条副对角线上的则x+y为定值。
令x1[i],x2[i],分别表示坐标差为i的主对角线上的方格的值之和、坐标和为i的副对角线上的方格的值之和。于是每个小方格该对谁有贡献就很清楚,遍历一遍加进去就ok。
(x1的下标这里暂且写作i,为了方便理解。然鹅因为是下标,还是取为正数比较好,所以代码里的下标会再加个n)
接下来就是两个bishops如何放置不会冲突的问题了。也是画一画能发现的,当x+y为偶数时,他的区域只会和x+y为偶数的点的区域重叠,和那些x+y为奇数的方格的区域则不会重叠的。x+y为奇数亦然。【这是个n*n矩阵】
所以想要取不会冲突的两个位置,就将点分成两个集合,各自找最大值就行。
具体操作见代码
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define ll long long
const int maxn=3e3+33;
ll a[maxn][maxn];
ll x1[3*maxn],x2[3*maxn];
ll n;
int main(){
scanf("%lld",&n);
for(ll i=1;i<=n;i++){
for(ll j=1;j<=n;j++){
scanf("%lld",&a[i][j]);
x1[i-j+n]+=a[i][j];
x2[i+j]+=a[i][j];
}
}
ll x_1,y_1,x_2,y_2;
ll max1,max2;
x_1=y_1=x_2=1;y_2=2;
max1=max2=0;
for(ll i=1;i<=n;i++){
for(ll j=1;j<=n;j++){
ll tmp=x1[i-j+n]+x2[i+j]-a[i][j];
if(tmp>max1&&(i+j)%2==1){
max1=tmp;x_1=i;y_1=j;
}else if(tmp>max2&&(i+j)%2==0){
max2=tmp;x_2=i;y_2=j;
}
}
}
printf("%lld\n",max1+max2);
printf("%lld %lld %lld %lld\n",x_1,y_1,x_2,y_2);
}