START:

2021-08-06

16:34:44

题目链接:

https://www.luogu.com.cn/problem/P2105

题目详情:

小 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

说明/提示

  • 对于 30% 的数据,1n,m5×10^3,1K500;
  • 对于另外 10% 的数据  K=1;
  • 对于 100% 的数据,1n,m2×10^4,1K500。

 

分析:

题目数据有那么亿点点大,所以正经的暴力是不行了,我们每放置一个皇后,用四个数组x[N],y[N],dig[N],udig[N],来储存该皇后

所在的行,列,对角线以及反对角线的状态,我们在图上画一个坐标系,给出任意几个点放置皇后,如下图:

 

 

 我们可以清楚的看到,点1的横纵坐标为(2,4),当点1放置一个皇后之后,第4行就被全被攻击了,第2列全被攻击,并且x+y=6上的点全被攻击了,以及x-y=-2上的点全被攻击了,所以在点(x,y)出放置一个皇后之后,我们更新所有的数组状态:

x[i]=1,y[j]=1,dig[x+y]=1,udig[x-y+C]=1

这里的udig[x-y+C]中,下标x-y加上常数C的原因是放置数组下标溢出,这就是我们的核心函数了。

在写核心函数之前,我们先写一个初始化函数,将所有的输入处理了

void init(){
    for(int i=1;i<=k;i++)
	{
        int a,b;
		scanf("%d%d",&a,&b);
		x[a]=1;
		y[b]=1;
		dig[a+b]=1;
		udig[a-b+C]=1;
	}
}

  

接着写核心函数fac()

int fac(){
    int res=0;
    for(int i=1;i<=n;i++){
        if(x[i])continue;
        for(int j=1;j<=m;j++){
            if(y[j]||dig[i+j]||udig[i-j+C])continue;
            else res++;
        }
    }
    return res;
}

  

最后这几个函数和程序基本框架结合起来

完整代码如下:

 (PS:需要开启氧气优化O2优化)

#include<iostream>
#include<cstdio>
using namespace std;
const int N=5e5+10;
const int C=2e4+10;
int n,m,k;
bool x[N],y[N],dig[N],udig[N];

int fac(){
    int res=0;
    for(int i=1;i<=n;i++){
        if(x[i])continue;
        for(int j=1;j<=m;j++){
            if(y[j]||dig[i+j]||udig[i-j+C])
          continue; else res++; } } return res; } void init(){ for(int i=1;i<=k;i++) { int a,b; scanf("%d%d",&a,&b); x[a]=1; y[b]=1; dig[a+b]=1; udig[a-b+C]=1; } } int main() { cin>>n>>m>>k; init(); cout<<fac()<<endl; return 0; }

  

end:

2021-08-06

16:59:16

posted on 2021-08-06 17:00  Dragon昴  阅读(203)  评论(3编辑  收藏  举报