C. Gargari and Bishops 思维 +对角线和维护

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).

Input
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.

Output
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.

Examples
inputCopy
4
1 1 1 1
2 1 1 0
1 1 1 0
1 0 0 1
outputCopy
12
2 2 3 2

很容易想到的一个做法就是 dfs ,两个对角线进行 dfs,并顺便打上标记,因为题目要求两个 bishop 的攻击位置不能重复,那么这个的复杂度怕是爆炸:因为你要求的是这两个和的 max,自然得每个都要枚举,我想到了这个后就没有做了,换了一种做法:
考虑对角线: y=x+b or y=-x+b; 由 b 可以唯一确定位置;
那么就可以先维护一个对角线和 sum ,然后 将 i+j 分奇偶即可;
复杂度 o(n^2) ;

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define maxn 200005
const int mod=1e9+7;
#define eps 1e-5
#define pi acos(-1.0)

ll quickpow(ll a,ll b)
{
    ll ans=1;
    while(b){
        if(b&1){
            ans=ans*a;
        }
        a=a*a;
        b>>=1;
    }
    return ans;
}
ll gcd(ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}

ll a[2005][2005];
ll sum[4005*3];
int x[2],y[2];
int main()
{
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    int i,j;
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            cin>>a[i][j];
        }
    }
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            sum[i+j]+=a[i][j];
            sum[i-j+3*n]+=a[i][j];
        }
    }
    ll ans1=-1,ans2=-1;
    ll res=0;
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
                res=0;
            res+=sum[i+j]+sum[i-j+3*n];
            res-=a[i][j];
            if((i+j)%2){
                if(ans1<res){
                    ans1=res;
                    x[0]=i;
                    y[0]=j;
                }
            }
            else {
                if(ans2<res){
                    ans2=res;
                    x[1]=i;
                    y[1]=j;
                }
            }
        }
    }
    cout<<ans1+ans2<<endl;
    cout<<x[0]<<' '<<y[0]<<' '<<x[1]<<' '<<y[1]<<endl;
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值