迷宫



分析



时间复杂度里的n,m写反了。

出题人很有举一反三的精神。

我的代码常数巨大,加了各种优化后开O3最慢点都要0.9s。

const int INF=0x3f3f3f3f;

const int MAXN=2e5+7;
int n,m;
int maze[6][MAXN]; struct node
{
int dis[6][6]; il node()
{
memset(dis,0x3f,sizeof dis);
} il int*operator[](rg const int&x)
{
return dis[x];
} il node operator+(rg const node&rhs)const
{
rg node res;
for(rg int i=1;i<=n;++i)
for(rg int j=1;j<=n;++j)
for(rg int k=1;k<=n;++k)
res[i][j]=min(res[i][j],dis[i][k]+rhs.dis[k][j]+1);
return res;
}
}; int ql,qr;
struct SegTree
{
node data[MAXN<<2];
int L[MAXN<<2],R[MAXN<<2];
#define lson (now<<1)
#define rson (now<<1|1)
il void build(rg int now,rg int l,rg int r)
{
L[now]=l,R[now]=r;
if(l==r)
{
for(rg int i=1;i<=n;++i)
for(rg int j=i;j<=n;++j)
{
if(maze[j][l])
data[now][i][j]=data[now][j][i]=j-i;
else
break;
}
return;
}
rg int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
data[now]=data[lson]+data[rson];
} il void change(rg int now)
{
if(L[now]==R[now])
{
memset(data[now].dis,0x3f,sizeof data[now].dis);
for(rg int i=1;i<=n;++i)
for(rg int j=i;j<=n;++j)
{
if(maze[j][L[now]])
data[now][i][j]=data[now][j][i]=j-i;
else
break;
}
return;
}
rg int mid=(L[now]+R[now])>>1;
if(ql<=mid)
change(lson);
else
change(rson);
data[now]=data[lson]+data[rson];
} il node qmin(rg int now)
{
if(ql<=L[now]&&R[now]<=qr)
return data[now];
rg int mid=(L[now]+R[now])>>1;
if(qr<=mid)
return qmin(lson);
if(ql>=mid+1)
return qmin(rson);
return qmin(lson)+qmin(rson);
}
}T; int main()
{
freopen("maze.in","r",stdin);
freopen("maze.out","w",stdout);
int q;
n=read(),m=read(),q=read();
for(rg int i=1;i<=n;++i)
for(rg int j=1;j<=m;++j)
maze[i][j]=read();
T.build(1,1,m);
while(q--)
{
static int opt,a,b,c,d;
opt=read();
if(opt==1)
{
a=read(),b=read();
maze[a][b]^=1;
ql=b;
T.change(1);
}
else
{
a=read(),b=read(),c=read(),d=read();
ql=b,qr=d;
rg int x=T.qmin(1)[a][c];
printf("%d\n",x<INF?x:-1);
}
}
// fclose(stdin);
// fclose(stdout);
return 0;
}

std的写法很优,不开O3都能0.9s。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define rg register
#define N 1<<19
#define INF 0x3f3f3f3f
char ch;void re(rg int& x)
{
while(ch=getchar(),ch<'!');x=ch-48;
while(ch=getchar(),ch>'!')x=x*10+ch-48;
}
using namespace std;
int n,m,q,l[N],r[N],p[6][N];
struct node
{
int dis[6][6];
node(){memset(dis,INF,sizeof dis);}
node operator + (const node& a)const
{
rg node tmp;
for(rg int i=1;i<=n;++i)
for(rg int j=1;j<=n;++j)
for(rg int k=1;k<=n;++k)
tmp.dis[i][j]=min(tmp.dis[i][j],dis[i][k]+a.dis[k][j]+1);
return tmp;
}
}data[N];
void build(rg int k,rg int a,rg int b)
{
l[k]=a,r[k]=b;
if(a == b)
{
for(rg int i=1;i<=n;++i)
for(rg int j=i;j<=n;++j)
if(p[j][a])
data[k].dis[i][j]=data[k].dis[j][i]=j-i;
else break;
return;
}
build(k<<1,a,a+b>>1);
build(k<<1|1,(a+b>>1)+1,b);
data[k]=data[k<<1]+data[k<<1|1];
}
void change(rg int k,rg int a)
{
if(l[k] == r[k])
{
memset(data[k].dis,INF,sizeof data[k].dis);
for(rg int i=1;i<=n;++i)
for(rg int j=i;j<=n;++j)
if(p[j][a])
data[k].dis[i][j]=data[k].dis[j][i]=j-i;
else break;
return;
}
if(a <= l[k]+r[k]>>1)change(k<<1,a);
else change(k<<1|1,a);
data[k]=data[k<<1]+data[k<<1|1];
}
node solve(rg int k,rg int a,rg int b)
{
if(a<=l[k] && b>=r[k])return data[k];
rg int mid=l[k]+r[k]>>1;
if(b<=mid)return solve(k<<1,a,b);
else if(a>mid)return solve(k<<1|1,a,b);
else return solve(k<<1,a,b)+solve(k<<1|1,a,b);
}
int main()
{
freopen("maze.in","r",stdin);
freopen("maze.out","w",stdout);
re(n),re(m),re(q);
for(rg int i=1;i<=n;++i)
for(rg int j=1;j<=m;++j)
re(p[i][j]);
build(1,1,m);
rg int opt,a,b,c,d;
while(q--)
{
re(opt),re(a),re(b);
if(opt == 1)
p[a][b]^=1,change(1,b);
else
{
re(c),re(d);
rg int x=solve(1,b,d).dis[a][c];
printf("%d\n",x<INF?x:-1);
}
}
}

Maze 2D

The last product of the R2 company in the 2D games' field is a new revolutionary algorithm of searching for the shortest path in a \(2 × n\) maze.

Imagine a maze that looks like a \(2 × n\) rectangle, divided into unit squares. Each unit square is either an empty cell or an obstacle. In one unit of time, a person can move from an empty cell of the maze to any side-adjacent empty cell. The shortest path problem is formulated as follows. Given two free maze cells, you need to determine the minimum time required to go from one cell to the other.

Unfortunately, the developed algorithm works well for only one request for finding the shortest path, in practice such requests occur quite often. You, as the chief R2 programmer, are commissioned to optimize the algorithm to find the shortest path. Write a program that will effectively respond to multiple requests to find the shortest path in a \(2 × n\) maze.

\(n,m \leq 2 \cdot 10^5\)

分析

考虑线段树,维护区间[l,r]内,四个角两两之间的距离。

  1. \(d_0\) 左上到右上
  2. \(d_1\) 左上到右下
  3. \(d_2\) 左下到右上
  4. \(d_3\) 左下到右下

合并时\(d_0=\min\{lson.d_0+rson.d_0,lson.d_1+rson.d_2\}+1\),其他同理。

时间复杂度\(O(n \log n + m \log n)\)

const int INF=0x7fffffff;

const int MAXN=2e5+7;
int n;
char maze[3][MAXN]; int ql,qr;
struct node
{
ll d[4]; ll&operator[](const int&x)
{
return d[x];
} node operator+(node rhs)
{
node res;
res[0]=min(d[0]+rhs[0],d[1]+rhs[2])+1;
res[1]=min(d[0]+rhs[1],d[1]+rhs[3])+1;
res[2]=min(d[2]+rhs[0],d[3]+rhs[2])+1;
res[3]=min(d[2]+rhs[1],d[3]+rhs[3])+1;
return res;
}
}; struct SegTree
{
node st[MAXN<<2];
#define lson (now<<1)
#define rson (now<<1|1)
void build(int now,int l,int r)
{
if(l==r)
{
int x=(maze[1][l]=='.'),y=(maze[2][l]=='.');
st[now][0]=x?0:2*n;
st[now][1]=st[now][2]=x&&y?1:2*n;
st[now][3]=y?0:2*n;
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
st[now]=st[lson]+st[rson];
} node qmin(int now,int l,int r)
{
/* cerr<<"qmin "<<now<<" "<<l<<" -> "<<r<<endl;
if(now==0)
system("pause");*/
if(ql<=l&&r<=qr)
return st[now];
int mid=(l+r)>>1;
if(qr<=mid)
return qmin(lson,l,mid);
if(ql>=mid+1)
return qmin(rson,mid+1,r);
return qmin(lson,l,mid)+qmin(rson,mid+1,r);
}
}T; int main()
{
// freopen("CF413E.in","r",stdin);
// freopen(".out","w",stdout);
int m;
read(n);read(m);
scanf("%s",maze[1]+1);
scanf("%s",maze[2]+1);
/* cerr<<"maze="<<endl;
cerr<<(maze[1]+1)<<endl;
cerr<<(maze[2]+1)<<endl;*/
T.build(1,1,n);
while(m--)
{
int u,v;
read(u);read(v);
if((u-1)%n+1>(v-1)%n+1)
swap(u,v);
// cerr<<"u="<<u<<" v="<<v<<endl;
int x1=(u>n)+1,x2=(v>n)+1;
ql=u-(x1-1)*n,qr=v-(x2-1)*n; // edit 1
// cerr<<"("<<x1<<" , "<<ql<<") -> ("<<x2<<" , "<<qr<<")"<<endl;
node ans=T.qmin(1,1,n);
// cerr<<"d="<<((x1-1)<<1|(x2-1))<<endl;
if(ans[(x1-1)<<1|(x2-1)]<2*n)
printf("%lld\n",ans[(x1-1)<<1|(x2-1)]);
else
puts("-1");
}
// fclose(stdin);
// fclose(stdout);
return 0;
}

考虑边界的时候base0和base1混用导致主函数代码很丑,将就着看。

注意给路径不通赋值时如果赋成2n要开long long

test20181005 迷宫的更多相关文章

  1. C语言动态走迷宫

    曾经用C语言做过的动态走迷宫程序,先分享代码如下: 代码如下: //头文件 #include<stdio.h> #include<windows.h>//Sleep(500)函 ...

  2. POJ 2251 Dungeon Master(3D迷宫 bfs)

    传送门 Dungeon Master Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 28416   Accepted: 11 ...

  3. BFS_Maze_求解迷宫最短路径

    /* 10 10 #.######.# ......#..# .#.##.##.# .#........ ##.##.#### ....#....# .#######.# ....#..... .## ...

  4. 【刷题笔记】I'm stuck! (迷宫)-----java方案

    题目描述 : 给定一个R行C列的地图,地图的每一个方格可能是'#', '+', '-', '|', '.', 'S', 'T'七个字符中的一个,分别表示如下意思: '#': 任何时候玩家都不能移动到此 ...

  5. canvas实例 ---- 制作简易迷宫(一)

    这个系列分为两部分,第一部分为迷宫的生成及操作,第二部分为自动寻路算法. 我们先看效果: See the Pen QGKBjm by fanyipin (@fanyipin) on CodePen. ...

  6. HTML 迷宫

    今天补个遗,将很久以前研究 HTML5 的时候写的生成迷宫.迷宫寻路程序整理出来. 下载链接在文章最后. 简介 为什么要做这个 HTML5 迷宫程序?因为我喜欢.我愿意.也是向老程序员学习(见第5节) ...

  7. 洛谷P1605 迷宫——S.B.S.

    题目背景 迷宫 [问题描述] 给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过.给定起点坐标和 终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案.在迷宫 中移动有上下 ...

  8. Java迷宫游戏

    缘起: 去年(大三上学期)比较喜欢写小游戏,于是想试着写个迷宫试一下. 程序效果: 按下空格显示路径: 思考过程: 迷宫由一个一个格子组成,要求从入口到出口只有一条路径. 想了一下各种数据结构,似乎树 ...

  9. K - 迷宫问题

    /*定义一个二维数组:  int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, ...

随机推荐

  1. 15分钟入门lua

    目录:[ - ] -- 1. Variables and flow control. -- 2. Functions. -- 3. Tables. -- 3.1 Metatables and meta ...

  2. Perfect Groups CodeForces - 980D

    链接 题目大意: 定义一个问题: 求集合$S$的最小划分数,使得每个划分内任意两个元素积均为完全平方数. 给定$n$元素序列$a$, 对$a$的所有子区间, 求出上述问题的结果, 最后要求输出所有结果 ...

  3. 新项目中使用的linux命令

    要通过跳板机进入内网之后,访问内网域名 mysql -h xxxxxxx -u u_caojiangjiang -p -P 3306 上传文件: scp -r /Users/qudian/Deskto ...

  4. Educational Codeforces Round 47 (Rated for Div. 2)F. Dominant Indices 线段树合并

    题意:有一棵树,对于每个点求子树中离他深度最多的深度是多少, 题解:线段树合并快如闪电,每个节点开一个权值线段树,递归时合并即可,然后维护区间最多的是哪个权值,到x的深度就是到根的深度减去x到根的深度 ...

  5. CentOS搭建“加速器”

    1.安装Shadowsocks 服务端 yum -y update yum install -y python-setuptools && easy_install pip pip i ...

  6. winform窗体this方式和handle(句柄)方式的区别

    我们来比较winform窗体的this方式和win32api handle方式实现窗体的最大化.默认窗体.半透明.不透明的区别 1.窗体界面设计 this方式按钮: btnMaxWindow. btn ...

  7. BZOJ1461 字符串的匹配

    什么字符串...明明是两个数列... 分类上来讲,还是一道很好的noip题...(雾) 首先,kmp会不会?(答:会!) 其次,树状数组求顺序对会不会?(再答:会!) 讲完了!>.< 进入 ...

  8. python爬虫常见面试题(一)

    前言 之所以在这里写下python爬虫常见面试题及解答,一是用作笔记,方便日后回忆:二是给自己一个和大家交流的机会,互相学习.进步,希望不正之处大家能给予指正:三是我也是互联网寒潮下岗的那批人之一,为 ...

  9. 玩转X-CTR100 l STM32F4 l HMC5983/HMC5883L三轴磁力计传感器

    我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ]      本文介绍X-CTR100控制器 扩展HMC ...

  10. SQL 递归找查所有子节点及所有父节

    在SQL的树型结构中,很多时候,知道某一节点的值,需要查找该节点的所有子节点(包括多级)的功能,这时就需要用到如下的用户自定义函数. 表结构如下: ID int Dep_Type int Dep_Co ...