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

先说一下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. 在Spring应用中创建全局获取ApplicationContext对象

    在Spring应用中创建全局获取ApplicationContext对象 1.需要创建一个类,实现接口ApplicationContextAware的setApplicationContext方法. ...

  2. JAVA邀请码生成器

    code import java.util.Random; /** * 邀请码生成器,算法原理:<br/> * 1) 获取id: 1127738 <br/> * 2) 使用自定 ...

  3. 2019.8.3 NOIP模拟测试12 反思总结【P3938 斐波那契,P3939 数颜色,P3940 分组】

    [题解在下面] 早上5:50,Gekoo同学来到机房并表态:“打暴力,打暴力就对了,打出来我就赢了.” 我:深以为然. (这是个伏笔) 据说hzoi的人还差两次考试[现在是一次了]就要重新分配机房,不 ...

  4. NIOP模拟17.10.13

    太水,简述一下题意 T1 让你计算一个形如Σai * bi^ki 快速幂即可 #include <iostream> #include <cstdio> #include &l ...

  5. poj 2406 Power Strings(KMP入门,next函数理解)

    Power Strings Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 37685   Accepted: 15590 D ...

  6. (一)学习SpringBoot介绍

    为什么去要用到SpringBoot 特点: 创建独立的spring应用 嵌入tomcat ,jetty不需要部署 提供starters poms简化maven配置 尽可能自动配置spring'应用 提 ...

  7. C++学习笔记(1)-构造函数与析构函数

    1.C++规定,每个类必须有默认的构造函数,没有构造函数就不能创建对象. 2.若没有提供任何构造函数,那么c++自动提供一个默认的构造函数,该默认构造函数是一个没有参数的构造函数,它仅仅负责创建对象而 ...

  8. python 布尔值索引

  9. Leetcode888.Fair Candy Swap公平的糖果交换

    爱丽丝和鲍勃有不同大小的糖果棒:A[i] 是爱丽丝拥有的第 i 块糖的大小,B[j] 是鲍勃拥有的第 j 块糖的大小. 因为他们是朋友,所以他们想交换一个糖果棒,这样交换后,他们都有相同的糖果总量.( ...

  10. 【水滴石穿】bstmy-blend-app

    这个项目是一个简单的底部导航切换页面 项目的地址为:https://github.com/Bstmy/bstmy-blend-app 先看效果 点击首页是首页面,点击个人中心是个人中心页面 先看代码 ...