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

先说一下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. ORACLE的Copy命令和create table,insert into的比较

    在数据表间复制数据是Oracle DBA经常面对的任务之一,Oracle为这一任务提供了多种解决方案,SQL*Plus Copy 命令便是其中之一.SQL*Plus Copy 命令通过SQL*Net在 ...

  2. Spring事务_注解_特性

    Spring 是一个 IOC 和 AOP 容器框架. ## 控制反转(IOC) ## 传统的 java 开发模式中,当需要一个对象时,我们会自己使用 new 或者 getInstance 等直接或者间 ...

  3. Django orm的惰性机制

    Django惰性机制 所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它并不会马上执行sql,而是当调用Quer ...

  4. LINUX配置文件介绍

    每个 Linux 程序都是一个可执行文件,它含有操作码列表,CPU 将执行这些操作码来完成特定的操作.例如,ls 命令是由 /bin/ls 文件提供的,该文件含有机器指令的列表,在屏幕上显示当前目录中 ...

  5. Lua报unexpected symbol near错误

    如果Lua脚本没有错误,那可能是UTF8 BOM的问题

  6. TYVJ2032 「Poetize9」升降梯上

    P2032 「Poetize9」升降梯上 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 开启了升降梯的动力之后,探险队员们进入了升降梯运行的那条竖直的隧道, ...

  7. JS 获取浏览器窗口大小 获取屏幕,浏览器,网页高度宽度

    网页可见区域宽:document.body.clientWidth 网页可见区域高:document.body.clientHeight 网页可见区域宽:document.body.offsetWid ...

  8. 洛谷3953 (NOIp2017) 逛公园——记忆化搜索+用栈判0环

    题目:https://www.luogu.org/problemnew/show/P3953 因为K只有50,所以想到用dp[ cr ][ j ]表示在点cr.比最短路多走了 j 的方案数.(看了TJ ...

  9. Linux C/C++开发

    首先就是要熟练在vim里面写代码,其实就是没有提示和自动补全了,这个问题并不大. 我服务器gcc版本是4.8.5,所以就按照这个来了 https://gcc.gnu.org/onlinedocs/gc ...

  10. 用Direct2D和DWM来做简单的动画效果2

    原文:用Direct2D和DWM来做简单的动画效果2 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/sunnyloves/article/detai ...