AtCoder ABC182 E - Akari

题意

给定一个h*w的地图,然后输入n个坐标,表示在这些位置上放置有灯泡;又输入m个坐标,表示在这些位置上放置石头。灯泡可以沿上下左右四个方向发射光线,光线会被石头挡住。现在问在这个地图上被照亮的方块有多少个。

思路

既然有四个方向,那么就分别从四个方向对地图进行标记。比如考虑光线朝左的情况,首先肯定要遍历整个地图,在每行刚开始的时候我们可以定一个flag,表示距离当前判定位置最近的石头的位置,如果找到新的石头,那么就更新flag的值;如果遇到灯泡,假设此时位置是j,那么就对flag+1~j这几个位置进行标记,全标记完把flag改为j,这样可以加快标记的速度,其他三个方向上的判断方法同理。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1505;
int mymap[N][N],is[N][N],ans;
int main(){
	int n,m,h,w,x,y;
	scanf("%d %d %d %d",&h,&w,&n,&m);
	for (int i=1;i<=n;i++){
		scanf("%d %d",&x,&y);
		mymap[x][y]=1;
	}
	for (int i=1;i<=m;i++){
		scanf("%d %d",&x,&y);
		mymap[x][y]=2;
	}
	//光线朝左 
	for (int i=1;i<=h;i++){
		for (int j=1,flag=0;j<=w;j++){
			if (mymap[i][j]==2)   flag=j;
			if (mymap[i][j]==1){
				for (int k=flag+1;k<=j;k++)   is[i][k]=1;
				flag=j;
			}
		}
	} 
	//光线朝右 
	for (int i=1;i<=h;i++){
		for (int j=w,flag=w+1;j>=1;j--){
			if (mymap[i][j]==2)   flag=j;
			if (mymap[i][j]==1){
				for (int k=flag-1;k>=j;k--)   is[i][k]=1;
				flag=j;
			}
		}
	} 
	//光线向下
	for (int i=1;i<=w;i++){
		for (int j=h,flag=h+1;j>=1;j--){
			if (mymap[j][i]==2)   flag=j;
			if (mymap[j][i]==1){
				for (int k=flag-1;k>=j;k--)   is[k][i]=1;
				flag=j;
			}
		}
	} 
	//光线向上
	for (int i=1;i<=w;i++){
		for (int j=1,flag=0;j<=h;j++){
			if (mymap[j][i]==2)   flag=j;
			if (mymap[j][i]==1){
				for (int k=flag+1;k<=j;k++)   is[k][i]=1;
				flag=j;
			}
		}
	} 
	//光线向下 
	for (int i=1;i<=h;i++){
		for (int j=1;j<=w;j++){
			if (is[i][j])   ans++;
		}
	}
	printf("%d",ans);
	return 0;
} 
posted @ 2020-11-09 23:52  一段时光  阅读(248)  评论(0)    收藏  举报