刺客信条

刺客信条

https://ac.nowcoder.com/acm/contest/6607/D

bfs/dfs/dijkstra +优先队列

起初看到这个题目我就想着一定是一个bfs的题,后面看大佬们的题解,发现大家都是用的dijkstra算法去做,因为求的是最短路嘛,但是因为这个题目的特殊性,dfs,bfs也可以用来求解最短路径,所以我就想每种方法都用一次

解法一:BFS+优先队列

#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;
            else
               b[i][j] = c[i][j] - '0';
         }
      printf("%d\n", bfs(sx, sy));
   }
}

解法二:dfs

其实dfs的代码思路和bfs差不多,一个用队列一个用递归

#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;
         else
            a[i][j] = c - '0';
      }
   dfs(sx, sy, 0);
   printf("%d\n", inf);
}

解法三:Dijkstra+堆优化

二维数组转一维然后跑一次dijkstra

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e3 + 7;
int n, m;
int map1[100][100];
int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
struct node
{
    int e, w, dis;
    bool operator<(const node &a) const
    {
        return w > a.w;
    }
};
vector<node> w[maxn];
priority_queue<node> q;
int dis[maxn], vis[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[t1.e] + w[t1.e][i].w < dis[v])
            {
                dis[v] = dis[t1.e] + w[t1.e][i].w;
                t2.e = v;
                t2.w = dis[v];
                q.push(t2);
            }
        }
    }
}
int main()
{
    while (~scanf("%d%d", &n, &m))
    {
        int s, e;
        char c;
        int end = (n - 1) * m + m - 1;
        for (int i = 0; i <= end; i++)
        {
            dis[i] = inf;
            vis[i] = 0;
            w[i].clear();
        }
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
            {
                cin >> c;
                if (c == 'A' || c == 'B' || c == 'C')
                    map1[i][j] = 100;
                else if (c == 'S')
                {
                    map1[i][j] = 0;
                    s = i * m + j;
                }
                else if (c == 'E')
                {
                    map1[i][j] = 0;
                    e = i * m + j;
                }
                else
                    map1[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 + dir[k][0];
                    int y = j + dir[k][1];
                    if (x < 0 || x >= n || y < 0 || y >= m)
                        continue;
                    t.e = x * m + y;
                    t.w = map1[x][y];
                    w[i * m + j].push_back(t);
                }
        Dijkstra(s);
        printf("%d\n", dis[e]);
    }
    return 0;
}
牛客课后习题题解 文章被收录于专栏

等待蜕变

全部评论

相关推荐

Java抽象带篮子:实习经历包装一下,可以看看我的包装贴
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
12-17 16:54
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务