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

先说一下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. Java问题解读系列之String相关---String、StringBuffer、StringBuilder的区别

    今天的题目是String.StringBuffer和StringBuilder的区别: 首先还是去官方的API看看对这三种类型的介绍吧,Go...... 一.继承类和实现接口情况 1.String类 ...

  2. 关于springmvc 只能在index.jsp页面显示图片的处理办法jsp页面无法显示图片

    首先,已经配置好了mvc对静态资源的处理 只有index,jsp可以显示图片 其他页面同样的代码则不显示 后来折腾了半天,发现 index是static的父目录的级别文件 可以向下访问 但是其他的js ...

  3. spring springmvc 展示图片,静态资源的处理

    jsp中显示一张照片 <img alt="静态图片" src="static/目录.png"> 然后在springmvc的配置中加上 <!-- ...

  4. 查询单表菜单是,sql

    START WITH CONNECT BY PRIOR这个语法主要用于查询数据包中的树型结构关系.先看下原始数据时怎么样的吧! 表中第一行1001是1002的父节点,而第二行1002又是1003的父节 ...

  5. eclipse2018整合tomcat9

    eclipse2018整合tomcat9 选择 Windows --> preferences --> server --> runtime environmen:点击“add”按钮 ...

  6. JS更改字体颜色、背景颜色

    CSS 颜色十六进制值  http://www.w3school.com.cn/cssref/css_colorsfull.asp CSS background-color 属性 body { bac ...

  7. IO流-文件操作

    一.字节流读/写 文件 1.字节流 方式读取文件

  8. iOS自动化打包上传的踩坑记

    http://www.cocoachina.com/ios/20160624/16811.html 很久以前就看了很多关于iOS自动打包ipa的文章, 看着感觉很简单, 但是因为一直没有AppleDe ...

  9. 廖雪峰Python总结3

    1.模块简介 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件中,这样每个文件包含的代码相对来说就比较少.一个.py文件就称之为一个模块(Module). 使用模块的好处: 提高了代码的可 ...

  10. Sublime Text2的常用技巧总结(更新中...)

    1. 选中一段内容后,按 Tab 或者 shift Tab 可以控制缩进 2. alt + shift + 数字, 开启多个窗口,数字代表分割后的个数,分割后按 Ctrl + shift + 数字 可 ...