牛客 刺客信条 (bfs、dijkstra)+堆优化、dfs三种求解
最短路
- BFS+优先队列
- DFS
- dijkstra+堆优化
题目描述
万物皆虚,万事皆允,玩过刺客信条的人对这句话应该都不会感到陌生
小A也是非常痴迷于这款游戏,正巧最近《刺客信条·奥德赛》发布了,然而其高昂的价格让小A苦恼不已
于是,小A只好重玩一次最经典的刺客信条2,来抚慰自己受伤的心灵
按照刺客信条2的剧情,艾吉奥需要前往威尼斯,从圣殿骑士手里夺取金苹果,然后前往罗马梵蒂冈刺杀教皇,拿取伊甸园神器“教皇权杖”
但是由于小A已经玩过很多次这个游戏了,他对剧情和地图了如指掌,现在已经轻而易举地拿到了金苹果,返回到了佛罗伦萨的庄园
接下来,小A就将操控艾吉奥从佛罗伦萨庄园出发,前往梵蒂冈,夺取教皇权杖。
在整个过程中,每经过一个建筑,都需要花费一定的时间,需要特别注意的是,由于圣母百花大教堂、圣马可大教堂、乔托钟楼都有众多圣殿骑士守护,经过这三个地方时,你需要花费100的时间
小A已经急不可耐地想要通关了,所以希望花费最少的时间到达梵蒂冈,请你帮他计算一下,从佛罗伦萨庄园到梵蒂冈,最快需要多少时间?
输入描述:
第一行有两个整数,表示地图的行数n和列数m,地图为一个n×m的矩阵
接下来有n行,每行m个字符,每个字符是一个数字或大写字母,数字表示经过该建筑需要的时间,字母表示特定建筑(S表示佛罗伦萨的庄园,即起点;E表示梵蒂冈,即终点;A表示圣母百花大教堂;B表示圣马可大教堂;C表示乔托钟楼;A、B、C在每组数据中至多出现一次),每个字符或数字之间用空格分隔
为了降低游戏难度,小A特意调小了地图
0≤n,m≤30
输出描述:
输出一个整数,从佛罗伦萨庄园到梵蒂冈的最小用时T
输入
3 3
S A E
1 2 3
1 B 3
输出
6
PS:起初看到这个题目我就想着一定是一个bfs的题,后面看大佬们的题解,发现大家都是用的dijkstra算法去做,因为求的是最短路嘛,但是因为这个题目的特殊性,dfs,bfs也可以用来求解最短路径,所以我就想每种方法都用一次
BFS+优先队列
bfs代码很形象就是首先把起点放入队列然后依次遍历这个点的周围四个点,然后放入队列,因为用了优先队列的优化,所以每次取栈顶元素(最小值)作为下一个遍历的起始点,然后依次按照之前的遍历,一旦遇到终点就返回最短路的值,还要判断一下边界,因为我们不能走出这个图!这个与dfs是一样的
其次这里我们用了一个小技巧去处理字符问题,为了不让回车和空格对我们所输入字符的干扰,我们在每次输入字符的前面加一个空格,这个它就会自动略去其他字符,当然也可以用c++标准输入输出,c++输入不会输入回车和空格字符。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100;
char c[maxn][maxn];
int sx, sy, ex, ey, n, m;
int d[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
int vis[maxn][maxn], b[maxn][maxn];
struct node
{int x, y, d;node(int xx, int yy, int dd) : x(xx), y(yy), d(dd) {}bool operator<(const node xx) const{return d > xx.d;}
};
int bfs(int x, int y)
{priority_queue<node> q;q.push(node(x, y, 0)); //首先把起点放入队列vis[x][y] = 1;while (!q.empty()){node xx = q.top();q.pop();if (xx.x == ex && xx.y == ey) //如果遇到了终点那么就返回当前距离return xx.d;for (int i = 0; i < 4; ++i) //依次遍历该点的上下左右节点{int nx = xx.x + d[i][0];int ny = xx.y + d[i][1];if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny]) //判断边界{int h = xx.d + b[nx][ny]; //当前距离加上下一个的距离vis[nx][ny] = 1;q.push(node(nx, ny, h));}}}
}
int main()
{while (~scanf("%d%d", &n, &m)){for (int i = 1; i <= n; ++i)for (int j = 1; j <= m; ++j){scanf(" %c", &c[i][j]); //这是一个小技巧,防止换行符和空格符号的干扰if (c[i][j] == 'S')sx = i, sy = j;else if (c[i][j] == 'E')ex = i, ey = j;else if (c[i][j] == 'A' || c[i][j] == 'B' || c[i][j] == 'C')b[i][j] = 100;elseb[i][j] = c[i][j] - '0';}printf("%d\n", bfs(sx, sy));}
}
DFS
dfs就是深度优先搜索,一条路走到黑,知道走到不能走为止,所以我们需要剪枝!!我们每走过一个点就要标记一次,递归是一层一层递归的,只要走过就标记,当然回退到上一次的话,就要把之前标记过的清除,因为要进行新的一轮递归。
#include <bits/stdc++.h>
using namespace std;
int a[100][100], vis[100][100];
int sx, sy, ex, ey, n, m;
int inf = 0x3f3f3f3f;
int d[4][2] = {-1, 0, 1, 0, 0, -1, 0, 1};
int xx[4] = {-1, 1, 0, 0}, yy[4] = {0, 0, -1, 1};
char c;
void dfs(int x, int y, int sum)
{if (x == ex && y == ey){inf = min(sum, inf);return;}if (sum >= inf)return;for (int i = 0; i < 4; ++i){int nx = x + d[i][0];int ny = y + d[i][1];if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny]){vis[nx][ny] = 1;dfs(nx, ny, sum + a[nx][ny]);vis[nx][ny] = 0;}}
}
int main()
{scanf("%d%d", &n, &m);for (int i = 1; i <= n; ++i)for (int j = 1; j <= m; ++j){cin >> c;//c++输入语言默认是不输入空格和回车的if (c == 'S')sx = i, sy = j;else if (c == 'E')ex = i, ey = j;else if (c == 'A' || c == 'B' || c == 'C')a[i][j] = 100;elsea[i][j] = c - '0';}dfs(sx, sy, 0);printf("%d\n", inf);
}
dijkstra+堆优化
dijkstra做这道题确实没想到的,但是后面仔细想想,确实是这样,因为题目要求的是最短路嘛,dijkstra是求最短路最高效的算法之一了,不过这个代码教之前的代码来看确实有点麻烦,但是理解起来是可以的,基本操作和思路还是差不多的,唯一有点新颖的就是它将二维数组转化成一维数组去操作
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10;
const int inf = 0x3f3f3f3f;
int d[4][2] = {-1, 0, 1, 0, 0, -1, 0, 1};
int a[maxn][maxn];
int vis[maxn], dis[maxn];
struct node
{int e, w;bool operator<(const node x) const{return w > x.w;}
};
priority_queue<node> q;
vector<node> w[maxn];
void dijkstra(int s)
{memset(dis, inf, sizeof(dis));memset(vis, 0, sizeof(vis));node t1, t2;t1.e = s;t1.w = 0;dis[s] = 0;q.push(t1);while (!q.empty()){t1 = q.top();q.pop();if (vis[t1.e])continue;vis[t1.e] = 1;for (int i = 0; i < w[t1.e].size(); ++i){int v = w[t1.e][i].e;if (!vis[v] && dis[v] > dis[t1.e] + w[t1.e][i].w){dis[v] = dis[t1.e] + w[t1.e][i].w;t2.e = v;t2.w = dis[v];q.push(t2);}}}
}
int main()
{int n, m, s, e;char c;scanf("%d%d", &n, &m);int end = (n - 1) * m + m - 1;for (int i = 0; i < n; ++i)for (int j = 0; j < m; ++j){cin >> c;if (c == 'S')a[i][j] = 0, s = i * m + j;else if (c == 'E')a[i][j] = 0, e = i * m + j;else if (c == 'A' || c == 'B' || c == 'C')a[i][j] = 100;elsea[i][j] = c - '0';}node t;for (int i = 0; i < n; ++i)for (int j = 0; j < m; ++j)for (int k = 0; k < 4; ++k){int x = i + d[k][0];int y = j + d[k][1];if (x < 0 || x >= n || y < 0 || y >= m)continue;t.e = x * m + y;t.w = a[x][y];w[i * m + j].push_back(t);}dijkstra(s);printf("%d\n", dis[e]);
}
五年之后生活—— 想和你窝在一张大大软软的床上,早上拉开一点窗帘, 然后和你相拥着看阳光一寸寸照进来 ,等到下午 换上身舒服的衣服,手拉着手去看场电影,再在天黑后压着马路回来,如果最后是你的话,等个三五年也没关系哒 (期待~) |
---|
牛客 刺客信条 (bfs、dijkstra)+堆优化、dfs三种求解相关推荐
- A - Age of Moyu HDU - 6386(Dijkstra+堆优化)
要解决这道题,可以用dfs+bfs,但是我不会,所以我只会dijkstra算法: 要解决这道题必须明白迪杰斯特拉算法的核心思想,我是这样理解的: 我可以任意举例一个图: 比如这个图,那么求1-6的最短 ...
- dijkstra堆优化(multiset实现-大大减小代码量)
例题: Time Limit: 1 second Memory Limit: 128 MB [问题描述] 在电视时代,没有多少人观看戏剧表演.Malidinesia古董喜剧演员意识到这一事实,他们想宣 ...
- 仿牛客网讨论社区项目—优化网站性能
性能优化: 1.考虑加入缓存优化 优化热门帖子列表 GitHub中搜索caffeine 在Maven Repository搜索caffeine配置文件,在resources文件包内的pom.xml文件 ...
- 2019牛客暑期多校训练营(第三场)H.Magic Line
2019牛客暑期多校训练营(第三场)H.Magic Line 题目链接 题目描述 There are always some problems that seem simple but is diff ...
- 2020牛客暑期多校训练营(第三场)A.Clam and Fish
2020牛客暑期多校训练营(第三场)A.Clam and Fish 题目链接 题目描述 There is a fishing game as following: The game contains ...
- 总结windows下堆溢出的三种利用方式
创建时间:2004-04-08 文章属性:转载 文章提交:watercloud (watercloud_at_xfocus.org) 原文由Leven发在网络编程版: https://www.xfoc ...
- * Dijkstra 堆优化
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/Mashiro_ylb/article/ ...
- poj1511 InvitationCards 最短路 Dijkstra堆优化
第一反应想到和 poj3268做法一样,先是从起点dj,然后将图反向,再次dj一次,求和即可.但是,数据O(n*n)过不去,所以需要使用dijkstra的堆优化! 淦,没用scanf结果超时了= = ...
- 寒假集训 最短路(I - Heavy Transportation)dijkstra+堆优化
今天的集训学习了最短路dijkstra的堆优化,把时间复杂度从朴素版的O()降至了O(n*logn+m). 首先,先上一段朴素版的代码. void dijkstra() {dist[1] = 0;fo ...
最新文章
- 复杂系统设计 企业开发的困境
- 授权管理【学习笔记】《卓有成效的管理者》 第二章 掌握自己的时间
- Android逆向--如何调试smali代码?
- mysql同步 触发器_mysql 触发器(数据库的同步)
- Spring @RequestParam批注
- ACCESS-类型转换函数
- 关于Markdown编辑器怎么写“|”等特殊符号的问题
- 一文读懂cooie和session
- [转][进阶]-Python3 异步编程详解
- 2021-2025年中国制冷机行业市场供需与战略研究报告
- 数据库一些开发者了解的操作
- jstat 监控调整GC很好用
- 【公告】4月15日CSDN下载频道和视频维护公告
- 2011年国内五款值得关注网店系统
- 51实验10: 独立按键控制一个数码管显示0-9,按一次只加1.
- python logging动态变更输出日志文件名
- fastapi官方文档翻译 -目录
- ubuntu系统下破解Clion
- 好看简洁的网站跳转页面
- 如何在命令行中使用 ftp 命令上传和下载文件