K皇后(根据对角线与行数计算列坐标)

昨天熬夜到一点半还是没写出来,一直死盯着屏幕,感觉眼球都要炸了,再加上熬夜对身体不好的焦虑,带着愤怒与无奈还是去睡了。早上起来又想了一个半小时,终于有了新的思路:
利用对角线的定值,计算出这一行与对角线相交的点的纵坐标,横坐标自然是这个点的行数,于是这个点的横纵坐标也就知道了。
题目链接:K皇后
题目大意:n行m列,给出k个皇后的位置,问棋盘上哪些位置不会被攻击到。
1 <= n, m <= 2e4, 1 <= k <= 500.
因为这题空间的限制实在是太严格,开二维数组要炸空间。而时间限制也仅是1s,O(N * M)的复杂度过不了。而O(N * (M + K) )的复杂度是可以的。
具体的做法是:
遍历每一行,如果这一行有皇后,那么ans -= m,并且continue。
如果这一行没有皇后,那么遍历每个皇后,检查当前的皇后是否能攻击到这一行中的某个点。
如果可以攻击到这一行中的某个点,则标记一下这个点的纵坐标。
记得要清空flag数组。

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 4e4 + 5;

bool hang[maxn], flag[maxn];
int n, m;
struct node {
	int x, y;
} G[maxn];

int main ()
{
	int k;
	cin >> n >> m >> k;
	for (int i = 1; i <= k; i++) {
		int x, y;
		scanf("%d%d", &x, &y);
		G[i].x = x; G[i].y = y;
		hang[x] = 1;
	}
	int ans = n * m;
	int ma = max(n, m);
	for (int i = 1; i <= n; i++) {
		if (hang[i] == 1) {
			ans -= m;
			continue;
		}
		memset(flag, 0, sizeof(flag));
		for (int j = 1; j <= k; j++) {
			int x = G[j].x, y = G[j].y;
			int y1 = -(x - y + ma) + i + ma;	//顺对角线定值
			int y2 = x + y - i;		//烦对角线定值
			if (flag[y] == 0) flag[y] = true,ans--;
			if (y1 >= 1 && y1 <= m && flag[y1] == 0) flag[y1] = true, ans--;
			if (y2 >= 1 && y2 <= m && flag[y2] == 0) flag[y2] = true, ans--;
		}
	}
	cout << ans;
	return 0;
}

这段代码还能小小的优化一下,flag数组可以开成int型的,然后用当前行数作为标记,如果flag[i]不等于当前行数那就是没有攻击过,然后把这个位置的值赋成当前行的行数。
如果还要优化的话,用快读的话应该还能再快一点。
O(N * M)的做法,如果开O2优化,也是能过的。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值