解法\(1:\)

正常的\(bfs\)剪枝是\(\Theta(nm4k)\),这个时间复杂度是只加一个\(vis\)记录的剪枝的,只能保证每个点只进队一次,并不能做到其他的减少时间,所以理论上是过不了的。\(n*m*4*k=4*10^9\)。

这里提供一个\(codeforces\)的官方解法:\(STL-set\)优化\(bfs\)。使用\(set\)主要是能够快速找到当前行和列有那个点没有被找到过,每行每列单独建立一个\(set\),\(set<int>\ line[N],col[N]\)。

在\(bfs\)的时候\(set<int>::iterator\ it=line[x].lower\_bound(y)\)找两次,分别处理左边和右边的答案。

再\(set<int>::iterator\ it=col[y].lower\_bound(x)\),分别处理上下方向的答案。

细节在代码里。

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
set<int> lin[N],col[N];
int n,m,k;
char mp[N][N];
int sx,sy,ex,ey;
queue<pair<int,pair<int,int> > > q;
int read()
{
int x=0,f=1;
char c=getchar();
while (c<'0'||c>'9')
{
if(c=='-') f=-1;
c=getchar();
}
while (c>='0'&&c<='9')
{
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
void add_to_que(int x,int y,int dis)
{
q.push(make_pair(dis,make_pair(x,y)));
lin[x].erase(y);
col[y].erase(x);
}
void BFS()
{
//int x1=read(),y=read()
add_to_que(sx,sy,0);
while (!q.empty())
{
int curx=q.front().second.first;
int cury=q.front().second.second;
int curd=q.front().first;
q.pop(); if(curx==ex && cury==ey)
{
printf("%d\n",curd);
exit(0);
}
set<int>::iterator wsy=lin[curx].lower_bound(cury); while (wsy!=lin[curx].end() && *wsy-cury<=k && mp[curx][*wsy]!='#')
{
add_to_que(curx,*wsy,curd+1);
wsy=lin[curx].lower_bound(cury);
}
wsy=lin[curx].lower_bound(cury);
while (wsy!=lin[curx].begin() && cury-*(--wsy)<=k && mp[curx][*wsy]!='#')
{
add_to_que(curx,*wsy,curd+1);
wsy=lin[curx].lower_bound(cury);
} wsy=col[cury].lower_bound(curx);
while (wsy!=col[cury].end() && *wsy-curx<=k && mp[*wsy][cury]!='#')
{
add_to_que(*wsy,cury,curd+1);
wsy=col[cury].lower_bound(curx);
}
wsy=col[cury].lower_bound(curx);
while (wsy!=col[cury].begin() && curx-*(--wsy)<=k && mp[*wsy][cury]!='#')
{
add_to_que(*wsy,cury,curd+1);
wsy=col[cury].lower_bound(curx);
}
}
puts("-1");
}
int main()
{
n=read(),m=read(),k=read();
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>mp[i][j],lin[i].insert(j),col[j].insert(i);
sx=read(),sy=read(),ex=read(),ey=read();
BFS();
return 0;
}

解法\(2:\)

卢神发现的一个\(\Theta(nm)\)的算法\((\)我也不知道是不是这个复杂度\()\)。

每次找一个点的时候,如果在更新答案时发现当前这个新的答案不比之前的更优的话,就直接\(break\),是的,直接退出循环。

为什么这样是对的呢?如果答案是从同一条路上来的,那么显然将来的答案不会更优。如果是拐弯过来的,那么显然按照之前的走更优。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int read()
{
int x=0,f=1;
char c=getchar();
while (c<'0'||c>'9')
{
if(c=='-') f=-1;
c=getchar();
}
while (c>='0'&&c<='9')
{
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
const int N=1005,inf=0x3f3f3f3f3f3f3f3f;
int n,m,k,sx,sy,ex,ey,dis[N][N],ans;
int dx[]={0,0,-1,1};
int dy[]={-1,1,0,0};
char ch[N][N];
queue<pair<int,int> >q;
int dij()
{
memset(dis,0x3f,sizeof(dis));
q.push(make_pair(sx,sy));
dis[sx][sy]=0;
while(!q.empty())
{
int x=q.front().first,y=q.front().second; q.pop();
for(int i=0;i<4;i++)
{
for(int j=1;j<=k;j++)
{
int nx=x+dx[i]*j,ny=y+dy[i]*j;
if(nx<1 || nx>n || ny<1 || ny>m || ch[nx][ny]=='#' || dis[nx][ny]<dis[x][y]+1) break;
if(dis[nx][ny]==inf)
{
dis[nx][ny]=dis[x][y]+1;
q.push(make_pair(nx,ny));
}
}
}
}
return dis[ex][ey];
}
signed main()
{
n=read(),m=read(),k=read();
for(int i=1;i<=n;i++) scanf("%s",ch[i]+1);
sx=read(),sy=read(),ex=read(),ey=read();
if(sx==ex && sy==ey) puts("0"),exit(0);
ans=dij();
printf("%lld",ans==inf?-1:ans);
return 0;
}

CodeForces CF877D题解(BFS+STL-set)的更多相关文章

  1. [Codeforces 1246B] Power Products (STL+分解质因数)

    [Codeforces 1246B] Power Products (STL+分解质因数) 题面 给出一个长度为\(n\)的序列\(a_i\)和常数k,求有多少个数对\((i,j)\)满足\(a_i ...

  2. luogu题解P1032字串变换--BFS+STL:string骚操作

    题目链接 https://www.luogu.org/problemnew/show/P1032 分析 这题本来很裸的一个BFS,发现其中的字符串操作好烦啊.然后就翻大佬题解发现用STL中的strin ...

  3. [codeforces 1037D] Valid BFS? 解题报告(验证bfs序,思维题)

    题目链接:http://codeforces.com/problemset/problem/1037/D 题目大意: 给出一棵树,询问一个序列是否可能为这棵树从节点1开始遍历的bfs序 题解: 对于每 ...

  4. Amr and Chemistry CodeForces 558C(BFS)

    http://codeforces.com/problemset/problem/558/C 分析:将每一个数在给定范围内(10^5)可变成的数(*2或者/2)都按照广搜的方式生成访问一遍,标记上访问 ...

  5. Gym 100952F&&2015 HIAST Collegiate Programming Contest F. Contestants Ranking【BFS+STL乱搞(map+vector)+优先队列】

    F. Contestants Ranking time limit per test:1 second memory limit per test:24 megabytes input:standar ...

  6. codeforces 1093 题解

    12.18 update:补充了 $ F $ 题的题解 A 题: 题目保证一定有解,就可以考虑用 $ 2 $ 和 $ 3 $ 来凑出这个数 $ n $ 如果 $ n $ 是偶数,我们用 $ n / 2 ...

  7. Codeforces 799B - T-shirt buying(STL)

    题目链接:http://codeforces.com/problemset/problem/799/B 题目大意:有n件T恤,每件T体恤都分别有价格(每件衣服的价格不重复).前面的颜色.背部的颜色三种 ...

  8. CodeForces 907E Party(bfs+状压DP)

    Arseny likes to organize parties and invite people to it. However, not only friends come to his part ...

  9. Kilani and the Game CodeForces - 1105D (bfs)

    Kilani is playing a game with his friends. This game can be represented as a grid of size n×mn×m, wh ...

随机推荐

  1. Dart & data type(static / dynamic)

    Dart & data type(static / dynamic) Darts 飞镖 标枪 javelin/darts type https://dartpad.dartlang.org/ ...

  2. web components & publish custom element & npm

    web components & publish custom element & npm https://www.webcomponents.org/publish Polymer ...

  3. NGK发力社区 打造三大社群模式

    当人们谈论区块链.数字货币的时候,常常会提到这样一些词汇:社区.社群,社区对区块链项目乃至于整个区块链行业的重要性已经形成了基本的行业共识,几乎每个项目方都在想尽办法营造社区.激发社区活力. 为什么区 ...

  4. ElasticSearch 文档及操作

    公号:码农充电站pro 主页:https://codeshellme.github.io 本节介绍 ES 文档,索引及其基本操作. 1,ES 中的文档 在 ES 中,文档(Document)是可搜索数 ...

  5. 1004 Counting Leaves ——PAT甲级真题

    1004 Counting Leaves A family hierarchy is usually presented by a pedigree tree. Your job is to coun ...

  6. Spring—Document root element "beans", must match DOCTYPE root "null"分析及解决方法

    网上很多人说要把applicationContex.xml文件中加上如下第二行的<!DOCTYPE/>标签,说明DTD.<?xml version="1.0" e ...

  7. [计算机图形学]绘制填充模型:重心坐标、z-buffer

    目录 一.点乘和叉乘 0. 向量表示 1. 点乘 2.叉乘 2.1 坐标运算方式 2.2 向量运算方式 2.3 叉乘的用途 二.Bounding Box 三.重心坐标 四.z-buffer 五.总结 ...

  8. 微信小程序:数据绑定

    data中的数据不仅仅可以当成文本来显示,还可以当成属性来显示. 注意:属性值要用单引号或双引号引起来. 在微信开发者工具的控制台中点击Wxml会看到 使用Boolean类型充当属性的时候,字符串和花 ...

  9. 看完了进程同步与互斥机制,我终于彻底理解了 PV 操作

    尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 CS-Wiki(Gitee 官 ...

  10. Dyno-queues 分布式延迟队列 之 辅助功能

    Dyno-queues 分布式延迟队列 之 辅助功能 目录 Dyno-queues 分布式延迟队列 之 辅助功能 0x00 摘要 0x01 前文回顾 0x2 Ack机制 2.1 加入Un-ack集合 ...