题目传送门


题目描述

有一个$n\times m$的格子图,其中有一些是黑色的,另一些为白色。
从某个白色格子的中心点向左上($NW$),左下($SW$),右上($NE$),右下($SE$)四个方向中的一个发出一束光线,若光线碰到黑色格子或者墙壁(即边界)会反射。反射情况如图所示:

我们不难发现,光线能穿过的格子总数是可以算出的。假如光线经过了某个格子的中心,则称光线经过了这个格子。求光线经过的格子总数。
由于答案可能很大,请使用$long\ long$的$C++$选手注意:请勿使用$\%lld$,推荐$cout$或者$\%I64d$


输入格式

第一行三个整数$n$、$m$、$k$,接下来$k$行每行两个整数$x_i$和$y_i$,表示第$i$个堵塞的格子的坐标。
最后一行两个整数$x_s,y_s$和一个字符串表示激光发出的方向。$“NE”,“NW”,“SE”,“SW”$分别表示方向$(-1,1),(-1,-1),(1,1),(1,-1)$。
保证输入的堵塞的格子坐标不重复。


输出格式

一行输出光束至少通过一次的空格子数。


样例

样例输入

7 5 3
3 3
4 3
5 3
2 1 SE

样例输出

14


数据范围与提示

$30\%$的数据,$n,m \leqslant 30$。

$60\%$的数据,$n,m \leqslant 1000$。

另$20\%$的数据,$k=0$。

$100\%$的数据,$n,m,k \leqslant 100,000$


题解

$30\%$算法:

我觉得这是这道题的难点所在,因为我到现在还想不出来$30\%$的算法怎么打。

$60\%$算法:

稍加思考,发现如果重复经过了某种状态,肯定已经循环过了一次。

想一想,一共有$n^2$个格子,$4$个方向,那么就有$4 \times n^2$个状态,暴力进去搜就好了。

不过需要注意以下几点:

  $1.$只有当当前状态被访问过了才可以跳出,并不是当前格子被访问过了。

  $2.$如果当前状态没有被访问过,但是当前格子被访问过了,答案不变。

时间复杂度:$O(4\times n^2)$。

期望得分:$60$分。

实际得分:$60$分。

另$20\%$算法:

考虑$k=0$,意思就是说,中间没有任何堵塞的格子,那么分为一下三种情况:

  $1.$如果$n \neq m$,那么不管从那个点往哪个方向出发,都一定把整张图全跑一遍,答案即为$n \times m$,记得开$long long$就好了。

  $2.$如果$n=m$,光线沿对角线发射,那么它会射到对角,再反弹回来,答案即为$n$。

  $3.$还是$n=m$,但是光线不沿对角线发射,那么它会转一圈,答案即为$2 \times n$。

期望多得分数:$10$分。

$100\%$算法:

  看一眼那$10^5$的数据范围,直接存图显然是不能接受的,那么我们这么考虑这个问题,用一个set存图,然后每次用二分法计算出下一个转向的位置,将答案加上,转向次数是$O(n+m+k)$级别的,每次查询是$O(\log k)$级别的,那么我们的理论最劣时间复杂度为:$O((n+m+k)\log k)$。

  根据题目中光线反射的方式,可以发现,每当光线沿$NW$、$SE$方向前进时,只会经过一种颜色的网格,每当光线沿$NE$、$SW$方向前进时,只会经过另一种颜色的网格。所以光线在某一个格子中心时,要么只会是$NW$、$SE$方向之一,要么只会是$NE$、$SW$方向之一,所以一个点最多只会被经过两次。

  易知,如果光线在前进过程中出现过如下两种反射,所有格子就会被经过两次。

  

  只需在模拟的过程中记录是否出现过这两种情况即可。


代码时刻

$60\%$算法:

#include<bits/stdc++.h>
using namespace std;
int n,m,k;
int ans;
bool Map[1001][1001];//记录堵塞
bool vis[1001][1001][5];//记录状态
void dfs(int x,int y,int w)
{if(vis[x][y][w])//出现了已经访问过的状态{printf("%d",ans);exit(0);}if(!vis[x][y][1]&&!vis[x][y][2]&&!vis[x][y][3]&&!vis[x][y][4])ans++;//如果这个点还没有被经过过vis[x][y][w]=1;//标记这种状态已经出现过if(w==1)//四个方向{if(!Map[x-1][y+1]){dfs(x-1,y+1,1);return;}//四种情况,小心别打错就好了if((Map[x-1][y]&&Map[x][y+1])||(!Map[x-1][y]&&!Map[x][y+1])){dfs(x,y,4);return;}if(Map[x-1][y]){dfs(x,y+1,3);return;}if(Map[x][y+1]){dfs(x-1,y,2);return;}}if(w==2){if(!Map[x-1][y-1]){dfs(x-1,y-1,2);return;}if((Map[x][y-1]&&Map[x-1][y])||(!Map[x][y-1]&&!Map[x-1][y])){dfs(x,y,3);return;}if(Map[x][y-1]){dfs(x-1,y,1);return;}if(Map[x-1][y]){dfs(x,y-1,4);return;}}if(w==3){if(!Map[x+1][y+1]){dfs(x+1,y+1,3);return;}if((Map[x+1][y]&&Map[x][y+1])||(!Map[x+1][y]&&!Map[x][y+1])){dfs(x,y,2);return;}if(Map[x+1][y]){dfs(x,y+1,1);return;}if(Map[x][y+1]){dfs(x+1,y,4);return;}}if(w==4){if(!Map[x+1][y-1]){dfs(x+1,y-1,4);return;}if((Map[x+1][y]&&Map[x][y-1])||(!Map[x+1][y]&&!Map[x][y-1])){dfs(x,y,1);return;}if(Map[x+1][y]){dfs(x,y-1,2);return;}if(Map[x][y-1]){dfs(x+1,y,3);return;}}
}
int main()
{scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=k;i++){int x,y;scanf("%d%d",&x,&y);Map[x][y]=1;}int x,y;char ch[5];//这个稍微开打点,因为输入最后会有'\0'。scanf("%d%d%s",&x,&y,ch+1);for(int i=0;i<=n+1;i++)Map[i][0]=Map[i][m+1]=1;//边界for(int i=0;i<=m+1;i++)Map[0][i]=Map[n+1][i]=1;if(ch[1]=='N'&&ch[2]=='E')dfs(x,y,1);if(ch[1]=='N'&&ch[2]=='W')dfs(x,y,2);if(ch[1]=='S'&&ch[2]=='E')dfs(x,y,3);if(ch[1]=='S'&&ch[2]=='W')dfs(x,y,4);return 0;
}

$100\%$算法:

#include<bits/stdc++.h>
using namespace std;
struct rec{int x,y,d;};
int n,m,k;
long long ans;//注意long long
set<int>s1[200010],s2[200010];
map<pair<int,int>,bool>mp;
int getid(int x,int y,int d){return d==1?x-y+m+1:x+y;}
bool same(rec a,rec b){if(a.x==b.x&&a.y==b.y&&a.d==b.d)return 1;return 0;}
bool check(int x,int y){return mp[make_pair(x,y)];}
void add(int x,int y)//标记堵塞
{s1[getid(x,y,1)].insert(x);s2[getid(x,y,2)].insert(x);mp[make_pair(x,y)]=1;
}
pair<rec,int> dfs(rec u)//暴力搜索
{rec re;set<int>::iterator it;if(u.d==1)//四个方向{it=s1[getid(u.x,u.y,1)].lower_bound(u.x);it--;//用set和lower_bound在log的时间复杂度内求出答案re.x=u.x-(abs(*it-u.x)-1);re.y=u.y-(abs(*it-u.x)-1);if(check(re.x-1,re.y)&&check(re.x,re.y-1))re.d=3;//枚举情况else if(check(re.x-1,re.y)){re.y--;re.d=4;}else if(check(re.x,re.y-1)){re.x--;re.d=2;}else re.d=3;}if(u.d==2){it=s2[getid(u.x,u.y,2)].lower_bound(u.x);it--;re.x=u.x-(abs(*it-u.x)-1);re.y=u.y+(abs(*it-u.x)-1);if(check(re.x-1,re.y)&&check(re.x,re.y+1))re.d=4;else if(check(re.x-1,re.y)){re.y++;re.d=3;}else if(check(re.x,re.y+1)){re.x--;re.d=1;}else re.d=4;}if(u.d==3){ it=s1[getid(u.x,u.y,1)].lower_bound(u.x);re.x=u.x+(abs(*it-u.x)-1);re.y=u.y+(abs(*it-u.x)-1);if(check(re.x+1,re.y)&&check(re.x,re.y+1))re.d=1;else if(check(re.x+1,re.y)){re.y++;re.d=2;}else if(check(re.x,re.y+1)){re.x++;re.d=4;}else re.d=1;}if(u.d==4){it=s2[getid(u.x,u.y,2)].lower_bound(u.x);re.x=u.x+(abs(*it-u.x)-1);re.y=u.y-(abs(*it-u.x)-1);if(check(re.x+1,re.y)&&check(re.x,re.y-1))re.d=2;else if(check(re.x+1,re.y)){re.y--;re.d=1;}else if(check(re.x,re.y-1)){re.x++;re.d=3;}else re.d=2;}return make_pair(re,abs(*it-u.x));
}
bool judge(rec u)
{rec re=u;do{pair<rec,int> cur=dfs(u);ans+=(long long)cur.second;switch(cur.first.d)//转向{case 1:if(u.d==3)return 0;break;case 2:if(u.d==4)return 0;break;case 3:if(u.d==1)return 0;break;case 4:if(u.d==2)return 0;break;}u=cur.first;}while(!same(re,u));return 1;
}
void pre_build()//处理边界
{for(int i=0;i<=m+1;i++){add(0,i);add(n+1,i);}for(int i=1;i<=n;i++){add(i,0);add(i,m+1);}
}
int main()
{scanf("%d%d%d",&n,&m,&k);pre_build();for(int i=1;i<=k;i++){int x,y;scanf("%d%d",&x,&y);add(x,y);}int x,y,d;char ch[5];scanf("%d%d%s",&x,&y,ch+1);if(ch[1]=='N'&&ch[2]=='W')d=1;if(ch[1]=='N'&&ch[2]=='E')d=2;if(ch[1]=='S'&&ch[2]=='E')d=3;if(ch[1]=='S'&&ch[2]=='W')d=4;rec st={x,y,d};st=dfs(st).first;if(!judge(st))//开始模拟{ans--;switch(st.d){case 1:st.d=3;break;case 2:st.d=4;break;case 3:st.d=1;break;case 4:st.d=2;break;}judge(st);}printf("%lld",ans);return 0;
}


rp++

转载于:https://www.cnblogs.com/wzc521/p/11228176.html

[Codeforces 274E]:Mirror Room(模拟)相关推荐

  1. CodeForces - 1526D Kill Anton(模拟)

    题目链接:https://vjudge.net/problem/CodeForces-1526D 题目大意:给出一个只有四种字母组成的字符串 AAA,要求将其重排列 BBB,使得贡献最大.贡献指的是, ...

  2. Codeforces Gym 100286I iSharp 模拟

    原题地址:http://codeforces.com/gym/100286/attachments/download/2013/20082009-acmicpc-northeastern-europe ...

  3. Pyramid of Glasses CodeForces - 676B (dp,模拟)

    题目:新冠病毒肆虐了好几个月,彻底打乱了大家的学习和生活,终于在阳光明媚的某月,全球迎来了新冠抗战的顺利.为了庆祝全球协力共同抗疫的顺利,同学们准备了一场庆祝晚会,一起幻想以后美好的生活,他们用香槟酒 ...

  4. Codeforces 770D Draw Brackets! 模拟+中缀表达式

    http://codeforces.com/problemset/problem/770/D 我先找出每个括号'+'的位置和每个s[i]的高度 括号一定会出现[],就是s[i]='[' s[i+1]= ...

  5. CodeForces - 1141ESuperhero Battle简单模拟

    Superhero Battle 这道题卡了我一个多小时,最后也没有做出来,成功称为吊车尾... 思路什么的都没有问题,主要是,爆long long了,这个太可怕了,就因为一个中间变量忘记开longl ...

  6. codeforces#239_div2_B Garland 简单模拟

    题目地址:戳这里 题目大意:剪成花环,可以cut 但是不能粘贴--那么最多的方案就是,对每一种具体的颜色,第一字符串中出现的次数和第二个字符串中出现的次数取较小值. 先以为not obliged to ...

  7. CodeForces 158 B. Taxi(模拟)

    [题目链接]click here~~ [题目大意]n组团体去包车,每组团体的人数<=4,一辆车最多容纳4人,求所求车的数目最小 [解题思路]:思路见代码~~ // C #ifndef _GLIB ...

  8. CodeForces 148C Terse princess(模拟)

    太坑了...这题 #include<iostream> #include<cstdio> #include<algorithm> #include<cstdl ...

  9. Codeforces Global Round 21 E. Placing Jinas

    Problem - E - Codeforces (Unofficial mirror by Menci) E. Placing Jinas 题目大意:每个点相当于(0,0)到每个点(只能向下和向右走 ...

  10. pd 生成mysql 脚本_PowerDesigner 如何生成数据库更新脚本

    最近在学习使用PowerDesigner 这个数据库设计工具,发现真的很强大,可以做很多事情,其中就涉及到如果数据库要进行更新了怎么办,主要是增加表,最麻烦的是修改字段名称,增加字段等操作,遇到主要的 ...

最新文章

  1. 小米note3无线显示电脑连接服务器,小米note3如何连接电脑 小米note3连接电脑没反应怎么办...
  2. 11款新品,一切为了落地!商汤:普惠AI的时代,来了
  3. Spirng使用Aspectj实现AOP
  4. iOS开发缓存机制之—内存缓存机制
  5. div覆盖div DIV相互重叠如何解决
  6. Java编程中程序员会遇到的一些感性烦恼,你有遇到吗?
  7. SQL核心语句(非常实用的几个技巧)
  8. 脚本格式(写脚本完成后最好完成后做一些脚本格式初始化)
  9. c3p0三种配置方式(automaticTestTable)
  10. SQL Server数据库表锁定原理以及如何解除表的锁定
  11. 力扣每日一刷--- 验证回文字符串II(非严格) 以及取反知识
  12. 唐山解封炉料大涨,PTA认购大涨,玻璃纯碱套利继续大跌2022.4.12
  13. 在用mybatis时报错java.lang.AbstractMethodError: com.mysql.jdbc.ServerPreparedState
  14. 视频演示 | 功能新增 | 增强版在线LEFSe分析和可视化鉴定标志性基因或物种
  15. linux逻辑卷缩减命令,linux命令:resize2fs、lvm逻辑卷lv扩展及缩减
  16. 基本了解云计算是什么东东了
  17. BeEF-XSS详细使用教程
  18. C++和java的异同点总结
  19. 眼底病php 是什么病,眼底病_眼底病有哪些_眼底病怎么治疗_快速问医生
  20. 大数据,why python

热门文章

  1. Codeforces 1090C New Year Presents
  2. 2022年:企业绩效管理蓝图
  3. lua脚本PHP加密网站源码,【几维安全】lua脚本加密,lua代码加密使用说明
  4. 短信注册验证以及邮箱激活
  5. 华为od机考真题-统计射击比赛成绩
  6. 计算机网络嗅探实验,网络嗅探与欺骗实验
  7. python上的包嗅探
  8. java swing choice_Java-GUI基础(三)java.swing
  9. 自定义view之无限滚动的刻度尺
  10. 面试官:谈谈你对geohash的理解和如何实现附近人功能呢?