牛客算法周周练17 D题 - 刺客信条 C++

题目链接:https://ac.nowcoder.com/acm/contest/6607/D

Description

万物皆虚,万事皆允,玩过刺客信条的人对这句话应该都不会感到陌生
小A也是非常痴迷于这款游戏,正巧最近《刺客信条·奥德赛》发布了,然而其高昂的价格让小A苦恼不已
于是,小A只好重玩一次最经典的刺客信条2,来抚慰自己受伤的心灵
按照刺客信条2的剧情,艾吉奥需要前往威尼斯,从圣殿骑士手里夺取金苹果,然后前往罗马梵蒂冈刺杀教皇,拿取伊甸园神器“教皇权杖”
但是由于小A已经玩过很多次这个游戏了,他对剧情和地图了如指掌,现在已经轻而易举地拿到了金苹果,返回到了佛罗伦萨的庄园

接下来,小A就将操控艾吉奥从佛罗伦萨庄园出发,前往梵蒂冈,夺取教皇权杖。
在整个过程中,每经过一个建筑,都需要花费一定的时间,需要特别注意的是,由于圣母百花大教堂、圣马可大教堂、乔托钟楼都有众多圣殿骑士守护,经过这三个地方时,你需要花费100的时间
小A已经急不可耐地想要通关了,所以希望花费最少的时间到达梵蒂冈,请你帮他计算一下,从佛罗伦萨庄园到梵蒂冈,最快需要多少时间?

Input

第一行有两个整数,表示地图的行数n和列数m,地图为一个n×m的矩阵
接下来有n行,每行m个字符,每个字符是一个数字或大写字母,数字表示经过该建筑需要的时间,字母表示特定建筑(S表示佛罗伦萨的庄园,即起点;E表示梵蒂冈,即终点;A表示圣母百花大教堂;B表示圣马可大教堂;C表示乔托钟楼;A、B、C在每组数据中至多出现一次),每个字符或数字之间用空格分隔
为了降低游戏难度,小A特意调小了地图
0≤n,m≤30

Output

输出一个整数,从佛罗伦萨庄园到梵蒂冈的最小用时T

Sample Input
3 3
S A E
1 2 3
1 B 3
Sample Output
6
Solution

显然这是个BFS的题,不过如果只用普通队列是不行的,因为有特定建筑的存在,导致最短距离不一定用时最短。这里我们可以使用一下优先队列,每次拿出用时最短的那个点去更新,直到到达终点即可。

Code
#include<iostream>
#include<algorithm>
#include<string>
#include<iomanip>
#include<set>
#include<queue>
#include<map>
using namespace std;
#define ll long long
char f[31][31];
bool vis[31][31];
int dx[4] = { 0,1,0,-1 };
int dy[4] = { 1,0,-1,0 };
int n, m, q, sx, sy, ex, ey;
struct node
{
	int x, y, t;//t表示起点到达点(x,y)所花的时间
	node(int m_x = 0, int m_y = 0, int m_time = 0) :x(m_x), y(m_y), t(m_time) {}
	bool operator<(const node& a) const {
		return t > a.t;
	}
};
int bfs() {
	priority_queue<node> p;
	p.push(node(sx, sy, 0));
	while (!p.empty())
	{
		node temp = p.top();
		p.pop();
		if (vis[temp.x][temp.y]) continue;
		vis[temp.x][temp.y] = 1;
		int xx, yy;
		for (int i = 0; i < 4; i++) {
			xx = temp.x + dx[i];
			yy = temp.y + dy[i];
            if (xx == ex && yy == ey) return temp.t;
			if (xx >= 0 && yy >= 0 && xx < n && yy < m  && vis[xx][yy] == 0) {
                if(f[xx][yy]=='A'||f[xx][yy]=='B'||f[xx][yy]=='C') p.push(node(xx, yy, temp.t + 100));
				else p.push(node(xx, yy, temp.t + int(f[xx][yy]-48)));
			}
		}
	}
}
int main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n >> m;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			vis[i][j] = 0;
		}
	}
    for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> f[i][j];
			if (f[i][j] == 'S') {
				sx = i; sy = j;
			}
			else if (f[i][j] == 'E') {
				ex = i; ey = j;
			}
		}
	}
	cout << bfs() << endl;
	return 0;
}

感觉有帮助的话,点个赞再走吧!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值