一道大模拟,打的我要吐了。

先说一下60%暴力吧,其实模拟光的路线即可,最好还是把边界设为障碍,这样就不用判边界了。最后输出n*m可以骗到10分。

注意不要把n和m弄混(愁死我了)。

 #include<iostream>
#include<cstdlib>
#include<cstdio>
#include<vector>
#define LL long long
#define int LL
using namespace std;
int n,m,k,xs,ys,f;
char te[];
bool map[][];
vector<short> v[][];
void dfs(int x,int y,int num,int fx)
{
// cout<<x<<" "<<y<<" "<<fx<<endl;
if(v[x][y].size()==)num++;
for(int i=;i<v[x][y].size();i++)if(v[x][y][i]==fx){cout<<num<<endl;exit();}
v[x][y].push_back(fx);
if(fx==)
{
if(x==&&y==m)dfs(x,y,num,);
else if(map[x-][y]&&map[x-][y+]&&map[x][y+])dfs(x,y,num,);
else if(x==||(y<m&&map[x-][y]&&map[x-][y+]))dfs(x,y+,num,);
else if(y==m||(x>&&map[x][y+]&&map[x-][y+]))dfs(x-,y,num,);
else if(map[x-][y+])dfs(x,y,num,);
else dfs(x-,y+,num,fx);
}
else if(fx==)
{
if(x==n&&y==m)dfs(x,y,num,);
else if(map[x+][y]&&map[x+][y+]&&map[x][y+])dfs(x,y,num,);
else if(x==n||(y<m&&map[x+][y]&&map[x+][y+]))dfs(x,y+,num,);
else if(y==m||(x<n&&map[x][y+]&&map[x+][y+]))dfs(x+,y,num,);
else if(map[x+][y+])dfs(x,y,num,);
else dfs(x+,y+,num,fx);
}//A
else if(fx==)
{
if(x==n&&y==)dfs(x,y,num,);
else if(map[x+][y]&&map[x+][y-]&&map[x][y-])dfs(x,y,num,);
else if(x==n||(y>&&map[x+][y]&&map[x+][y-]))dfs(x,y-,num,);
else if(y==||(x<n&&map[x][y-]&&map[x+][y-]))dfs(x+,y,num,);
else if(map[x+][y-])dfs(x,y,num,);
else dfs(x+,y-,num,fx);
}
else if(fx==)
{
if(x==&&y==)dfs(x,y,num,);
else if(map[x-][y]&&map[x-][y-]&&map[x][y-])dfs(x,y,num,);
else if(x==||(y>&&map[x-][y]&&map[x-][y-]))dfs(x,y-,num,);
else if(y==||(x>&&map[x][y-]&&map[x-][y-]))dfs(x-,y,num,);
else if(map[x-][y-])dfs(x,y,num,);
else dfs(x-,y-,num,fx);
}
}
signed main()
{
// freopen("ray0.in","r",stdin); cin>>n>>m>>k;
if(n>||m>) {cout<<n*m<<endl;exit();}
int a,b;
for(int i=;i<=k;i++)
{
cin>>a>>b;
if(n<=&&m<=)map[a][b]=;
}
cin>>xs>>ys>>te;
for(int i=;i<=m+;i++)map[][i]=map[n+][i]=;
for(int i=;i<=n+;i++)map[i][]=map[i][m+]=;
if(te[]=='N')
{
if(te[]=='E')f=;
else f=;//W
}
else//S
{
if(te[]=='E')f=;
else f=;//W
}
if(n<=&&m<=)
dfs(xs,ys,,f);
}

暴力

然后说正解(其实就是优化了暴力):

确实有点难以理解,对于光的路线,可以发现其实暴力中间枚举了很多无用的状态,怎么解决呢?

有一个比较简单但是不好想的规律,对于斜线,x+y或x-y不变,那么我们就可以用这个数字代表一条斜线,对于每一条斜线开一个set,将这条斜线上的障碍的x插入,那么二分查找就可以实现快速地转移了。

然而这样递归下去还是比较麻烦的,可以用循环。

再说两个规律:光线经过的路径只可能是环而不是环+链(显然),一条路径中至多出现两次原路返回的情况(这个自己想想也不难,其实是我不会证)。

所以循环处理即可,具体见代码。

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<set>
#include<map>
#define LL long long
#define MAXN 200010
#define MP(a,b) make_pair(a,b)
#define ma(x) memset(x,0,sizeof(x))
using namespace std;
int n,m,k;
int xs,ys;char te[];
LL ans=;
struct rec{int x,y,d;};
set<int> s1[MAXN],s2[MAXN];
map<pair<int,int>,bool>mp;
int getid(int x,int y,int d){return d==?x-y+m+:x+y;}
bool same(rec a,rec b){if(a.x==b.x&&a.y==b.y&&a.d==b.d)return ;return ;}
bool check(int x,int y){return mp[MP(x,y)];}
void add(int x,int y)
{
s1[getid(x,y,)].insert(x);
s2[getid(x,y,)].insert(x);
mp[MP(x,y)]=;
}
pair<rec,int> dfs(rec u)
{
rec re;
set<int>::iterator it;
if(u.d==)
{
it=s1[getid(u.x,u.y,)].lower_bound(u.x);it--;
re.x=u.x-(abs(*it-u.x)-);
re.y=u.y-(abs(*it-u.x)-);
if(check(re.x-,re.y)&&check(re.x,re.y-))re.d=;
else if(check(re.x-,re.y))re.d=,re.y--;
else if(check(re.x,re.y-))re.d=,re.x--;
else re.d=;
}
if(u.d==)
{
it=s2[getid(u.x,u.y,)].lower_bound(u.x);it--;
re.x=u.x-(abs(*it-u.x)-);
re.y=u.y+(abs(*it-u.x)-); if(check(re.x-,re.y)&&check(re.x,re.y+))re.d=;
else if(check(re.x-,re.y))re.d=,re.y++;
else if(check(re.x,re.y+))re.d=,re.x--;
else re.d=;
}
if(u.d==)
{
it=s1[getid(u.x,u.y,)].lower_bound(u.x);
re.x=u.x+(abs(*it-u.x)-);
re.y=u.y+(abs(*it-u.x)-); if(check(re.x+,re.y)&&check(re.x,re.y+))re.d=;
else if(check(re.x+,re.y))re.d=,re.y++;
else if(check(re.x,re.y+))re.d=,re.x++;
else re.d=;
}
if(u.d==)
{
it=s2[getid(u.x,u.y,)].lower_bound(u.x);
re.x=u.x+(abs(*it-u.x)-);
re.y=u.y-(abs(*it-u.x)-); if(check(re.x+,re.y)&&check(re.x,re.y-))re.d=;
else if(check(re.x+,re.y))re.d=,re.y--;
else if(check(re.x,re.y-))re.d=,re.x++;
else re.d=;
}
return MP(re,abs(*it-u.x));
}
bool judge(rec u)
{
rec re=u;
do
{
pair<rec,int> cur=dfs(u);
ans+=cur.second;
switch(cur.first.d)
{
case :if(u.d==)return ;break;
case :if(u.d==)return ;break;
case :if(u.d==)return ;break;
case :if(u.d==)return ;break;
}
u=cur.first;
}while(!same(re,u));
return ;
} signed main()
{
// freopen("in.txt","r",stdin); cin>>n>>m>>k;
for(int i=;i<=m+;i++)add(,i),add(n+,i);
for(int i=;i<=n;i++) add(i,),add(i,m+);
int a,b;
for(int i=;i<=k;i++)
{
cin>>a>>b;
add(a,b);
}
int f;
cin>>xs>>ys>>te;
if(te[]=='N')
{
if(te[]=='E')f=;
else f=;//W
}
else//S
{
if(te[]=='E')f=;
else f=;//W
}
rec st={xs,ys,f};
st=dfs(st).first;
if(!judge(st))//判断第一次反向
{
ans--;
switch(st.d)
{
case :st.d=;break;
case :st.d=;break;
case :st.d=;break;
case :st.d=;break;
}
judge(st);
}
cerr<<ans<<endl;
cout<<ans<<endl;
}

HZOJ 光的更多相关文章

  1. 搭建自己私有的PKM系统,各家PKM大比拼。。附:构建自己熟悉的基础Docker,破解联通光猫

    Docker这容器真是很好玩!干啥都想上docker了,快疯了. 这不,最近wiz笔记开始收费,很是不爽,需要寻求新的PKM系统了.备选及落选理由如下: wiz笔记 -- 好用,顺手.要开始收费了,不 ...

  2. webform 光棒效果,删除操作弹出确定取消窗口

    鼠标移入onmouseover和鼠标移出onmouseout,代码里没大写我这也就不大写了.那首先,我们得获取Class为tr_item里的所有东西,也就是项标签里的数据.然后呢,我们定义一个oldC ...

  3. 兼容可控硅调光的一款LED驱动电路记录

    1.该款电路为兼容可控硅调光的LED驱动电路,采用OB3332为开关控制IC,拓扑方案为Buck: 2.FB1:磁珠的单位是欧姆,而不是亨利,这一点要特别注意.因为磁珠的单位是按照它在某一频率 产生的 ...

  4. Arduino 极速入门系列 - 光控灯(3) - 光敏电阻、与电阻分压那些事

    继续是讲解基础原理,新手专用部分.这次讲光敏电阻,和用电阻分压.光电元器件有好几种,其中测光相关的元器件,常见的有光敏三极管和光敏电阻,我们这次光控灯用光敏电阻.在我们光控灯里面,将会使用它搭建出分压 ...

  5. Arduino 极速入门系列 - 光控灯(2) - 关于开关,上拉、下拉电阻那些事

    接上篇,这次继续讲解光控灯的另外两个组成部分 - 开关和光敏电阻,光控灯里面将会有自锁开关按钮和光敏电阻.这此主要给新玩电子的朋友解释一下开关按钮的做法. 开关按钮的引脚电平读取问题 - 新手专用 我 ...

  6. Arduino 极速入门系列 - 光控灯(1)- 关于理论和 LED 那些事

    点个 LED 闪亮好像太单调,这次来个光控 LED 灯.这个其实不需要 Arduino 也能做,这次只是用来演示一下 PWM 在 Arduino 里面的做法.PWM 原理后面会解释.这次用充电宝提供 ...

  7. 关于紫光a5扫描仪的安装

    同事需要扫描写东西,从别的机器上搬来紫光a5的扫描仪,不会安装,需要帮忙. 插上扫描仪,win7提示发现新硬件,开始自动安装驱动.等了一会儿,提示无法安装,看来得手工寻找驱动来安装了.上网搜索a5的驱 ...

  8. 实战之中兴ZXHN F460光猫破解超级密码+开启无线路由功能

    本文面向小白用户,即使你不懂电脑看完你也会破解光猫,网上有些文章的操作方法是错误的.按照我这篇文章,只要型号对,那么肯定没问题!电信光纤入户,家里用的是电信送的中兴查看 ZXHN F460 中的全部文 ...

  9. Atitit.iso格式蓝光 BDMV 结构说明

    Atitit.iso格式蓝光 BDMV 结构说明 1. Iso是个复合文件1 2. Iso内部格式如下1 2.1. Bdmv文件夹格式 BDMV(Blu-ray Disk Movie.BD-MV),为 ...

随机推荐

  1. Python之路,Day3- Python基础(转载Alex)

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...

  2. 使用neo4j-import导入数据及关系

    背景 上节我们了解了什么是图数据库,作为研究对象的neo4j的特点,优缺点以及基本的环境搭建. 现在我们要讲存储在csv中的通话记录数据导入到neo4j中去,并且可以通过cql去查询导入的数据及关系 ...

  3. python无法启动火狐浏览器且报错“selenium.common.exceptions.WebDriverException: Message: Unable to find a matching set of capabilities”

    安装了python2,使用pip安装了selenium,但是在使用时,报了“selenium.common.exceptions.WebDriverException: Message: 'gecko ...

  4. free内存监控

    语 法: free [-bkmotV][-s <间隔秒数>] 补充说明:free指令会显示内存的使用情况,包括实体内存,虚拟的交换文件内存,共享内存区段,以及系统核心使用的缓冲区等. 参 ...

  5. linux环境变量设置命令

    1echo $ <变量名> //显示某个环境变量 2env     // environment (环境) 的简写,列出来所有的环境变量 3set     //显示所有本地定义的Shell ...

  6. Leetcode78. Subsets子集

    给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: nums = [1,2,3] 输出: [ [3],   [1],   [2 ...

  7. 将jacoco集成到测试工具平台

    最近在做接口测试,想通过代码覆盖率来判断一下接口用例是否缺失,但是每次通过命令来生成覆盖率报告,感觉太麻烦,所以就想着把jacoco集成到测试工具平台中,只需要点几个按钮,就能查看到覆盖率报告. 测试 ...

  8. LUOGU 3089 后缀排序(模板)

    传送门 解题思路 这是一个神奇的算法,sa[i]表示排名第i为的元素是啥,rk[i]表示第i个元素排名是啥.然后使用基数排序+倍增的思想去处理.主要是参考的这位大佬的博客(https://www.cn ...

  9. CF1067E Random Forest Rank

    CF1067E Random Forest Rank 可以证明: 一个树的邻接矩阵的秩,等于最大匹配数*2(虽然我只能证明下界是最大匹配) 而树的最大匹配可以贪心, 不妨用DP模拟这个过程 f[x][ ...

  10. 注解1 --- JDK内置的三个基本注解 --- 技术搬运工(尚硅谷)

    @Override: 限定重写父类方法, 该注解只能用于方法 @Deprecated: 用于表示所修饰的元素(类, 方法等)已过时.通常是因为所修饰的结构危险或存在更好的选择 @SuppressWar ...