Safe Path(bfs+一维数组存图)

题目链接:http://codeforces.com/gym/101755/problem/H

题目分析:先bfs一遍怪兽可以到达的点,再bfs人可以走的地方看可不可以到达终点;

     很显然读到  2<=n*m<=200000 时,就不可以用二维数组存图了,不过据说因为数据比较水,可以用vector存图;

vector存图AC代码:

  1 /* */
  2 # include <iostream>
  3 # include <stdio.h>
  4 # include <string.h>
  5 # include <string>
  6 # include <cmath>
  7 # include <climits>
  8 # include <cctype>
  9 # include <ctime>
 10 # include <algorithm>
 11 # include <functional>
 12 # include <bitset>
 13 # include <set>
 14 # include <map>
 15 # include <deque>
 16 # include <queue>
 17 # include <stack>
 18 # include <vector>
 19 using namespace std;
 20
 21 const int maxn=2e5+7;
 22 vector<char>mp[maxn];
 23 vector<int>dis[maxn];
 24 vector<int>vis[maxn];
 25 int n, m;
 26
 27 struct node
 28 {
 29     int x, y;
 30     int step;
 31 }cur, after;
 32
 33 int dir[4][2]={{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
 34 int sx, sy, fx, fy;
 35
 36 int check(int x, int y)
 37 {
 38     if( x>=0 && x<n && y>=0 && y<m )
 39         return 1;
 40     return 0;
 41 }
 42
 43 void bfs1(int d)
 44 {
 45     queue<node>q;
 46     int i, j;
 47     for( i=0; i<n; i++ )
 48     {
 49         for( j=0; j<m; j++ )
 50         {
 51             if( mp[i][j]==‘M‘ )
 52             {
 53                 cur.x = i;
 54                 cur.y = j;
 55                 cur.step = 0;
 56                 q.push(cur);
 57                 dis[i][j] = 1;
 58             }
 59         }
 60     }
 61
 62     while( !q.empty() )
 63     {
 64         cur = q.front();
 65         q.pop();
 66         for(int i=0; i<4; i++ )
 67         {
 68             after.x = cur.x+dir[i][0];
 69             after.y = cur.y+dir[i][1];
 70             after.step = cur.step + 1;
 71
 72             if( check(after.x, after.y) )
 73             {
 74                 if( !dis[after.x][after.y] && after.step<=d )
 75                 {
 76                     dis[after.x][after.y] = 1;
 77                     q.push(after);
 78                 }
 79             }
 80         }
 81     }
 82 }
 83
 84 void bfs2(int x, int y)
 85 {
 86     cur.x = x;
 87     cur.y = y;
 88     cur.step = 0;
 89     queue<node>q;
 90     q.push(cur);
 91     vis[x][y] = 1;
 92     if( dis[x][y] )
 93     {
 94         printf("-1\n");
 95         return ;
 96     }
 97     while( !q.empty() )
 98     {
 99         cur = q.front();
100         q.pop();
101         if( mp[cur.x][cur.y]==‘F‘ )
102         {
103             printf("%d\n", cur.step);
104             return ;
105         }
106         for(int i=0; i<4; i++ )
107         {
108             after.x = cur.x + dir[i][0];
109             after.y = cur.y + dir[i][1];
110             after.step = cur.step + 1;
111             if( check(after.x, after.y) )
112             {
113                 if( !dis[after.x][after.y] && !vis[after.x][after.y])
114                 {
115                     vis[after.x][after.y] = 1;
116                     q.push(after);
117                 }
118             }
119         }
120     }
121     printf("-1\n");
122     return ;
123 }
124 int main()
125 {
126     int d, i, j;
127     cin>>n>>m>>d;
128     char s;
129
130     for(i=0; i<n; i++)
131     {
132         mp[i].clear();
133         vis[i].clear();
134         dis[i].clear();
135     }
136
137     for(i=0; i<n; i++ )
138     {
139         for(j=0; j<m; j++ )
140         {
141             cin>>s;
142             mp[i].push_back(s);
143             dis[i].push_back(0);
144             vis[i].push_back(0);
145         }
146     }
147     bfs1(d);
148
149     for(i=0; i<n; i++ )
150     {
151         for( j=0; j<m; j++ )
152         {
153             if( mp[i][j]==‘F‘ )
154             {
155                 fx = i;
156                 fy = j;
157             }
158             if( mp[i][j]==‘S‘ )
159             {
160                 sx = i;
161                 sy = j;
162             }
163         }
164     }
165
166     if( dis[fx][fy] )
167     {
168         printf("-1\n");
169     }
170     else
171     {
172         bfs2(sx, sy);
173     }
174     return 0;
175 }

这道题也让我知道了可以用一位数组存图:

详细的见代码注释:

AC代码:

  1 /* */
  2 # include <iostream>
  3 # include <stdio.h>
  4 # include <string.h>
  5 # include <algorithm>
  6 # include <cctype>
  7 # include <ctime>
  8 # include <functional>
  9 # include <cmath>
 10 # include <bitset>
 11 # include <deque>
 12 # include <queue>
 13 # include <stack>
 14 # include <vector>
 15 # include <set>
 16 # include <map>
 17 # include <climits>
 18 using namespace std;
 19
 20 typedef long long LL;
 21 const int maxn=1e6+100;
 22 int n, m, t;
 23 int a[maxn], d;
 24 char str[maxn];
 25 bool vis[maxn];///标记是否已经访问过
 26 int dis[maxn];///记录步数
 27 int dd[maxn];///dd[]为0,说明怪兽到不了,dd不为0说明怪兽可以到此处
 28 int cnt, fx, fy, sx, sy;
 29 int dir[4][2]={{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
 30 struct node
 31 {
 32     int x;
 33     int y;
 34 }g[maxn], cur, after;
 35
 36 bool check(int a, int b)
 37 {
 38     if( a>=1 && b>=1 && a<=n && b<=m && !dd[a*m+b] )
 39         return true;
 40     return false;
 41 }
 42
 43 void bfs()
 44 {
 45     queue<node>q;
 46     cur.x = sx;
 47     cur.y = sy;
 48     vis[cur.x*m+cur.y] = 1;
 49     q.push(cur);
 50
 51     while( !q.empty())
 52     {
 53         cur = q.front();
 54         q.pop();
 55         for(int i=0; i<4; i++ )
 56         {
 57             int xx = cur.x + dir[i][0];
 58             int yy = cur.y + dir[i][1];
 59
 60             if( check(xx, yy) && !vis[xx*m+yy])
 61             {
 62                 dis[xx*m+yy] = dis[cur.x*m+cur.y]+1;
 63                 vis[xx*m+yy] = 1;
 64                 after.x = xx;
 65                 after.y = yy;
 66                 q.push(after);
 67             }
 68         }
 69     }
 70     return ;
 71 }
 72
 73 void bfss()///广搜怪兽可以到达的地方
 74 {
 75     queue<node>q;
 76     for(int i=0; i<cnt; i++ )
 77         q.push(g[i]);
 78
 79     while( !q.empty() )
 80     {
 81         cur=q.front();
 82         q.pop();
 83
 84         if( dd[cur.x*m+cur.y]==0 )
 85             continue;
 86
 87         for(int i=0; i<4; i++ )
 88         {
 89             int xx = cur.x + dir[i][0];
 90             int yy = cur.y + dir[i][1];
 91             if( check(xx, yy) )
 92             {
 93                 after.x = xx;
 94                 after.y = yy;
 95                 dd[xx*m+yy] = dd[cur.x*m+cur.y]-1;
 96                 q.push(after);
 97             }
 98         }
 99     }
100     return ;
101 }
102
103 int main()
104 {
105     while( ~ scanf("%d %d %d", &n, &m, &d) )
106     {
107         getchar();
108         for(int i=1; i<=n; i++ )
109             scanf("%s", &str[i*m+1]);///一维数组存图
110
111         memset(vis, false, sizeof(vis));
112         memset(dd, 0, sizeof(dd));
113         memset(dis, 0, sizeof(dis));
114
115         for(int i=1; i<=n; i++ )
116         {
117             for(int j=1; j<=m; j++ )
118             {
119                 if( str[i*m+j]==‘S‘ )
120                 {
121                     sx = i;
122                     sy = j;
123                 }
124
125                 else if( str[i*m+j]==‘F‘ )
126                 {
127                     fx = i;
128                     fy = j;
129                 }
130
131                 else if( str[i*m+j]==‘M‘ )
132                 {
133                     dd[i*m+j] = d+1;
134                     cur.x = i;
135                     cur.y = j;
136                     g[cnt++] = cur;
137                 }
138             }
139         }
140
141         bfss();
142         if( dd[sx*m+sy] || dd[fx*m+fy] )
143         {
144             printf("-1\n");
145         }
146         else
147         {
148             bfs();
149             if( !vis[fx*m+fy] )
150                 printf("-1\n");
151             else
152                 printf("%d\n", dis[fx*m+fy]);
153         }
154     }
155     return 0;
156 }

原文地址:https://www.cnblogs.com/wsy107316/p/11327168.html

时间: 2024-08-01 01:12:34

Safe Path(bfs+一维数组存图)的相关文章

Codeforces gym101755H Safe Path(bfs)

题意: 给以一个网格图,有起点终点和一些怪兽,可以上下左右走,不能走到距离怪兽曼哈顿距离为d以内的地方,问到终点最短路径 n*m<=2e5,d<=2e5 思路: 因为n*m的范围,不能直接建2e5*2e5的图,所以要vector.resize() 如果对每个怪兽都预处理的话,复杂度将是O(d2) 所以我们可以让所有怪兽同时走,这样预处理只有O(nm),也可以证明不会漏情况 代码: #include<iostream> #include<cstdio> #include&

生化危机 邻接表存图+BFS

生化危机 发布时间: 2015年10月10日 18:05   时间限制: 1000ms   内存限制: 256M 描述 X博士想造福人类, 研发一种可以再生肢体的药物, 可是很不幸......研究失败了, 他在蜥蜴身上实验的时候, 蜥蜴发生了变异, 更糟糕的是, 蜥蜴逃出了生化实验室. 恐怖的事情发生了, 疫情以X博士所在的城市为中心向四周扩散开, 最终, 整个地球上的城市都被感染了.假设整个地球一共有N个城市, 这N个城市是连通的, 有N-1条通道把他们连接起来.病毒会以一座城市为中心,在一天

结构体语法梳理2-指针与一维数组

结构体指针与结构体数组 1.1 指针复习 对于指针的理解,我们一方面从语法层面上理解,一方面编译器角度理解会发生什么事情. type  *p = value; p+i   的结果是 value+sizeof(type)*i 对于指针变量p ,*前面的type决定了 如何通过p存储的地址去访问内存. 比如 int  *p1 = 0x10; char *p2 = 0x10; double  *p3 = 0x10; *p1 从 0x10地址处访问四个字节,并且把这四个字节的数据当int类型来看. *p

B - Cow Marathon DFS+vector存图

After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to get more exercise, so he has committed to create a bovine marathon for his cows to run. The marathon route will include a pair of farms and a path comprised of a se

java 数据结构 图中使用的一些常用算法 图的存储结构 邻接矩阵:图的邻接矩阵存储方式是用两个数组来标示图。一个一位数组存储图顶点的信息,一个二维数组(称为邻接矩阵)存储图中边或者弧的信息。 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 实例如下,左图是一个无向图。右图是邻接矩阵表示:

以下内容主要来自大话数据结构之中,部分内容参考互联网中其他前辈的博客. 图的定义 图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示一个图,V是图G中顶点的集合,E是图G中边的集合. 无边图:若顶点Vi到Vj之间的边没有方向,则称这条边为无项边(Edge),用序偶对(Vi,Vj)标示. 对于下图无向图G1来说,G1=(V1, {E1}),其中顶点集合V1={A,B,C,D}:边集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}: 有向图:若

结对开发Ⅴ——循环一维数组求和最大的子数组

一.设计思路 (1)数据的存储结构是链表,最后一个结点的next指向第一个元素的结点: (2)数据个数为n,则最多有n*(n+(n-1)+...+1)种情况(包括重复): (3)剩下的部分与二维数组的差不多. 二.源代码 1 // 一维数组.cpp : Defines the entry point for the console application. 2 // 袁佩佩 于海洋 3 4 #include "stdafx.h" 5 #include<iostream.h>

一维数组对象转成二维数组

一.关于PHP把装着item为对象的一维数组转成二维数组的疑问 背景:新增帖子的时候,选择标签时,可以选择多个,后端接口是需要传入的是一个二维数组. /** * @Title 修改精选内容 * @Params $id 记录ID * @Params $tags 标签组 array( * array( * 'name' => '桌面文化', * 'tag_id' => '2' * ) */ public function update($id = 0,$tags = array()) 困惑:后端接

一维数组建模表示二维的棋盘状态

当我们想写一个棋类游戏的时候,不难发现,很多棋类游戏的棋盘都可以用一个二维数组表示,比如: 井字棋(3*3的二维数组).黑白棋(8*8的二维数组).五子棋(15*15的二维数组)等等 使用二维数组表示棋盘,数组的下标就是棋子的坐标,数组中的值就是棋子的状态. 好处就是数据访问比较直观,可直接根据下标快速找到某个位置的棋子的状态. 但缺点也是很明显的 比如: 首先是遍历棋盘需要用双重循环处理横坐标跟纵坐标: 其次是判断棋子状态,比如以上所说的三种棋子,需要判断行.列以及斜线8个方向上的棋子状态,因

指针知识梳理2-指针与一维数组

一.一维数组复习 数组的本质是连续的内存,我们可以通过一下代码验证. int main() { int a[10]; int i; for(i = 0;i<10;i++) { printf("%p\n",&a[i]); } } 打印出每个元素的地址,会发现地址间隔是4 ,这个间隔刚好等于sizeof(int). 那么如果知道了a[0]的地址,我们就可以通过地址的加减算出a[i]的地址,然后访问a[i]; 二.通过指针访问一维数组 指针能够访问一维数组的两个前提是: 1.内