K皇后
题目描述
小Z最近捡到了一个棋盘,他想在棋盘上摆放K个皇后。他想知道在他摆完这K个皇后之后,棋盘上还有多少了格子是不会被攻击到的。
(Ps:一个皇后会攻击到这个皇后所在的那一行,那一列,以及两条对角线)
输入格式
第一行三个正整数 n,m,K,表示棋盘的行列,以及小Z摆放了K个皇后。
接下来K行,每行两个正整数x,y,表示这个皇后被摆在了第x行,第y列,数据保证没有任何两个皇后会被摆在同一个格子里。
输出格式
一行一个整数,表示棋盘上还有多少了格子是不会被攻击到的。
一道数学+思维的题目;
刚开始想直接暴搜,交了只要20分,TLE和MLE,发现这道题给我的空间只要30MB,开二维数组肯定不行;
必须换种思路,枚举行,然后再枚举每个皇后,判断每个皇后对当前行是否有贡献,注意一下边界就行;数学的思维体现在知道一个点、斜率,和另一个点的横坐标,求另一个点的纵坐标;
代码:
#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define lson k<<1
#define rson k<<1|1
//ios::sync_with_stdio(false);
using namespace std;
const int N=1000100;
const int M=200100;
const LL mod=1e9+7;
int n,m,k;
int x[20010],y[20010];
bool v[20010];
bool vis[20010];
int main(){
ios::sync_with_stdio(false);
cin>>n>>m>>k;
for(int i=1;i<=k;i++){
cin>>x[i]>>y[i];
v[x[i]]=true;
}
int s=0;
for(int i=1;i<=n;i++){//x
if(v[i]) continue;
memset(vis,false,sizeof(vis));
int ans=m;
for(int j=1;j<=k;j++){
if(vis[y[j]]==false) ans--;
vis[y[j]]=true;
int y1=i-x[j]+y[j];//斜率为1
if(y1>=1&&y1<=m&&vis[y1]==false){
ans--;
vis[y1]=true;
}
int y2=x[j]-i+y[j];//斜率为-1
if(y2>=1&&y2<=m&&vis[y2]==false){
ans--;
vis[y2]=true;
}
}
s+=ans;
}
cout<<s<<endl;
return 0;
}