AT_abc182_e [ABC182E] Akari 题解
题目大意
已知在一个
正解思路
-
记录下每个灯泡的坐标
和 ,定义一个二维数组 ,如果该格子上有障碍物,就把 中这一格的值赋为2,如果是灯泡,赋值为一。定义一个布尔类型的二维数组 ,记录每个格子有没有光照。定义一个 类型的变量 ,记录有多少个格子有光照,定义一个变量 ,记录当前的状态。 -
对于每个格子,我们可以根据上下左右四个方向的格子的状态更新。因此,按照从上到下、从下到上、从左到右、从右到左的四个顺序遍历整个网格,每次遍历前把
的值初始化为1。如果该格是灯泡,那么把 的值赋为1,如果是障碍物,那么赋值为0。这时,一个格子的光照状态就可以根据 来更新了:如果这个格子在这一次更新之前就已经有光照了,那么不更新;如果 的值为1,说明之前的格子及当前格子中没有障碍物,也就是说,这个格子是一定会有光照的,那么我们把这个格子的 更新为1;如果 的值为0,说明当前格子或当前格子之前的个子中已经有障碍物了,说明光线无法到达,赋值为0。简而言之,如果当前格子的 为1,那么最后他的 值也为1;如果当前格子的 为0,那么它 的值就等于 的值。到这里,我们惊奇的发现,这不就是逻辑或吗!所以我们可以得到关系式 。 -
最终,我们只需要遍历一遍整个网格,如果格子的
值为1,那么 。遍历完后输出 就可以了。
时间复杂度:
AC代码
#include<iostream>
#pragma GCC opzitime(2)
using namespace std;
inline void read(int &x){
x=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-f;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
x*=f;return;
}
inline void put(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) put(x/10);
putchar(x%10+'0');return;
}inline void write(int x){put(x);putchar('\n');}
int Nu1,Nu2,n,m,x,y,cnt,now;
int map[1505][1505];
bool vis[1505][1505];
inline void work(){
for(int i=1;i<=n;i++){
now=0;
for(int j=1;j<=m;j++){//从上到下,从左到右更新
if(map[i][j]==2) now=0; //如果这个格子本身就是障碍物,now=0
else if(map[i][j]==1)//如果这个格子本身就是光源,那么now-1
now=1,vis[i][j]|=now;//同时更新vis
else vis[i][j]|=now;//如果这是空格子,根据now更新
}
now=0;
for(int j=m;j>=1;j--){//从上到下,从右到左更新
if(map[i][j]==2) now=0; //如果这个格子本身就是障碍物,now=0
else if(map[i][j]==1)//如果这个格子本身就是光源,那么now-1
now=1,vis[i][j]|=now;//同时更新vis
else vis[i][j]|=now;//如果这是空格子,根据now更新
}
}
for(int j=1;j<=m;j++){
now=0;
for(int i=1;i<=n;i++){//从左到右,从上到下更新
if(map[i][j]==2) now=0; //如果这个格子本身就是障碍物,now=0
else if(map[i][j]==1)//如果这个格子本身就是光源,那么now-1
now=1,vis[i][j]|=now;//同时更新vis
else vis[i][j]|=now;//如果这是空格子,根据now更新
}
now=0;
for(int i=n;i>=1;i--){//从左到右,从下到上更新
if(map[i][j]==2) now=0; //如果这个格子本身就是障碍物,now=0
else if(map[i][j]==1)//如果这个格子本身就是光源,那么now-1
now=1,vis[i][j]|=now;//同时更新vis
else vis[i][j]|=now;//如果这是空格子,根据now更新
}
}
}
signed main(){
read(n),read(m),read(Nu1),read(Nu2);
for(register int i=1;i<=Nu1;i++)//读入灯泡坐标
read(x),read(y),map[x][y]=1;
for(register int i=1;i<=Nu2;i++)//读入障碍物坐标
read(x),read(y),map[x][y]=2;
work();int cnt=0;
for(int i=1;i<=n;i++){//计算共有多少个格子有光照
for(int j=1;j<=m;j++){
if(vis[i][j]) cnt++;
}
}
write(cnt);//输出
return 0;
}
蒟蒻的第一篇题解,求过。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下