P2105 K皇后

题目描述

小 Z 最近捡到了一个棋盘,他想在棋盘上摆放 K 个皇后。他想知道在他摆完这 K 个皇后之后,棋盘上还有多少个格子是不会被攻击到的。

注意:一个皇后会攻击到这个皇后所在的那一行,那一列,以及两条对角线。

输入格式

第一行三个正整数 n,m,K,表示棋盘的行列,以及小 Z 摆放的皇后的个数。

接下来 K 行,每行两个正整数 x,y,表示这个皇后被摆在了第 x行,第 y 列,数据保证任何两个皇后都不会被摆在同一个格子里。

输出格式

仅一个整数,表示棋盘上还有多少个格子是不会被攻击到的。

输入输出样例

输入 #1

12 13 6
10 4
12 10
1 1
2 3
3 2
2 6

输出 #1

25

分析:

由于数据范围较大,暴力会超时;

正确做法:

记录下输入的每个皇后之后,从每一行开始遍历;如果该行有皇后,直接跳出;

如果该行没有皇后,设该行行数为i,初始时该行不被攻击的格子数为m;

遍历每一个K皇后;判断其列和两条对角线是否影响该行某个位置;

如果某个K皇后影响了第i行某列,就用c[]数组标记该位置,并且该行不被攻击的格子数-1;

(好像分析的有点绕口,不懂的可以再看看注释)

注:数组c用来标记某个位置是否已有K皇后攻击过,由于被K皇后攻击过后,该行不被攻击的格子数-1,故用数组c标记防止重复相减。

AC代码(含注释):

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> PII;

int n, m;
int k;
int x[510], y[510];
int c[20010];//用来标记该位置是否被攻击的数组
int ans = 0;//棋盘上不会被攻击到的格子数
int main()
{
	cin >> n >> m >> k;
	for (int i = 1; i <= k; i++) cin >> x[i] >> y[i];
	//从每行开始遍历
	for (int i = 1; i <= n; i++) {
		int num = m;//初始时每行格子数为m
		for (int j = 1; j <= k; j++) {//遍历每个K皇后
			if (x[j] == i) {//若该行有K皇后,直接跳出;
				num = 0; 
				break;
			}
			else {//如果该行没有皇后,判断其他K皇后的列和两条对角线是否影响该行某个位置;
				if (c[y[j]] != i) {//判断列;初始时c[y[j]] != i;一旦该列有K皇后,就标记该位置
					c[y[j]] = i;
					num--;
				}
				if (x[j] + y[j] - i >= 1 && x[j] + y[j] - i <= m && c[x[j] + y[j] - i] != i) {//判断左下—右上对角线
					num--;
					c[x[j] + y[j] - i] = i;
				}
				if (y[j] + (i - x[j]) >= 1 && y[j] + (i - x[j]) <= m && c[y[j] + (i - x[j])] != i) {//判断左上-右下对角线
					num--;
					c[y[j] + (i - x[j])] = i;
				}
			}
		}
		ans += num;//每行扫描结束后加上该行不会被攻击到的格子数
	}
	cout << ans;
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值