【每日一题】codeforces 463C (1900) (数学)

每日一题,坚持使我强大


今日份快乐:codeforces 463C 传送门
明天份快乐:洛谷 P1219 传送门 (八皇后问题,正好用到这个对角线的知识)


题目大意

一个n*n的棋盘上,每个格子都有一个价值,现在在棋盘上放置两个主教(象),每个主教都可以攻击其所在对角线上的所有点(包括主教所在的点,但只能算一次),并获得其价值,但是两个主教不能攻击同一个格子。
问:如何放置两个主教才能获得最大价值,这两个点在哪,最大打价值是什么。

分析

如果了解过国际象棋的规则就会很简单,国际象棋的棋盘是黑白交替的,每方有两个主教,分别在黑格和白格上。

                                                     来自百度百科
我们可以发现,如果要满足两个主教不攻击同一个格子,那么这两个主教肯定是一个在黑格上,一个在白格上。这样对角线才不会出现相交,可以用反证法手动验证(让他俩在同一个颜色的格子上)。
在确定这两个主教的位置关系后,我们就要来选择主教的位置了。


科普一个知识:
中从左上角到右下角的对角线叫主对角线
中从右上角到左下角的对角线叫次对角线


对于任意点(x, y),这个点的价值为:主对角线的价值和 + 次对角线的价值和 - 这个点的价值。我们遍历每个点,找到白格的最大值和黑格的最大值,就OK。
现在有两个问题:

  • first:如何确定当前点是白格还是黑格
  • second:如何计算对角线的和

我们分别来回答这两个问题。
对于问题一:
我们可以发现,对于任意点(x, y),有:
             如果 x + y 是偶数,则这个点是白格
             如果 x + y 是奇数,则这个点是黑格
我们可以通过 x + y 的奇偶性来判断是黑格还是白格
对于问题二:

我们看一个图
在这里插入图片描述
我计算几条次对角线的下标和,我们可以发现,同一条次对角线上的点的下标和相同
(这个图黄色标记的格子都为国际象棋中的白格,他们的下标和都是偶数,和他们相邻一个格子的点下标和肯定都为奇数,也就是黑格)


同样的,主对角线是不是存在这样的性质呢?
通过计算我们可以得到,同一条主对角线上的点的 x - y + n 的值相同
通过这两个结论,我们就可以在输入数据的时候计算对角线的和,再遍历求最大值就OK

接下来就是代码实现了,超详细代码附上

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;

ll mp[2005][2005] = {0};	
ll v_l[4005] = {0};          		// 主对角线价值和,要注意 x + y   的最大范围是两倍的 n  
ll v_r[4005] = {0};			// 次对角线价值和 ,同样 x - y + n 的最大范围也是两倍的 n  

int main() {

	ios::sync_with_stdio(false);
	
 	int n;
 	cin >> n;
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= n; j++){
			cin >> mp[i][j];
			v_l[i - j + n] += mp[i][j];		// 计算主对角线价值和  
			v_r[i + j] += mp[i][j];			// 计算次对角线价值和 
		}
	}
	
	int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
	ll mx1 = -1, mx2 = -1;
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= n; j++){
			ll sum = v_l[i - j + n] + v_r[i + j] - mp[i][j];	// 该点的价值和 
			if((i + j) % 2 == 0){					// 偶数为白格 
				if(sum > mx1){
					mx1 = sum;
					x1 = i;
					y1 = j;
				}
			}
			else{							// 奇数为黑格 
				if(sum > mx2){
					mx2 = sum;
					x2 = i;
					y2 = j;
				}
			}
		}
	}
	
	cout << mx1 + mx2 << endl;
	cout << x1 << " " << y1 << " " << x2 << " " << y2 << endl;
	
    return 0;
}

欢迎大佬们留言指错

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值