牛客算法周周练17D - 刺客信条(dfs剪枝 | 优先队列 + bfs)

在这里插入图片描述在这里插入图片描述

题目大意:

给出一张n * m的地图,每经过一个建筑都需要一定的时间,而经过ABC要花费100,要求输出从S到E的最短时间。

解题思路:

思路一:dfs剪枝
输入地图的时候用char输入,然后转成int型即可,然后dfs跑图,因为有多条路到达E而取最短,所以维护一个最小值ans,如果当前没到E,而步数 >= ans,则return,如果当前到了,则ans和s取一个最小值。AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <cstring>
using namespace std;
const int N = 35;
int mp[N][N], mmin = 0x7fffffff, n, m;
int x, y, xx, yy;
int xn[4]={-1,1,0,0},ynn[4]={0,0,-1,1};//这里用一维比二维快,如果用二维就会TLE
bool book[N][N];
char st;
void dfs(int x0, int y0, int s)
{
    if (x0 == xx && y0 == yy)
    {
        mmin = min(s, mmin);
        return;
    }
    if (s >= mmin)//剪枝
      return;
    for (int k = 0; k < 4; k ++)
    {
        int tx = x0 + xn[k];
        int ty = y0 + ynn[k];
        if (tx < 1 || tx > n || ty < 1 || ty > m || book[tx][ty])
          continue;
        book[tx][ty] = true;
        dfs(tx, ty, s + mp[tx][ty]);
        book[tx][ty] = false;
    }
    return;
}
int main()
{
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++)
        {
            cin >> st;
            if (isdigit(st))
              mp[i][j] = st - '0';
            else if (st == 'A' || st == 'B' || st == 'C')
                mp[i][j] = 100;
            else if (st == 'S')
                x = i, y = j;
            else if (st == 'E')
                xx = i, yy = j;;
        }
    book[x][y] = true;
    dfs(x, y, 0);
    cout << mmin << endl;
    return 0;
}

dfs思路学到了开两个一维数组表示方向比二维的[4][2]要快,如果一维就不会超时,二维则会TLE

思路二:优先队列优化bfs
用优先队列存放当前的点,用权值排序,以保证当前走到的点一定是多条路之中最小的,那么第一次到E点的值即为最小值。AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <cstring>
#include <queue>
using namespace std;
const int N = 35;
struct node
{
    int x, y, sum;
    bool operator < (const node &t)const
    {
        return sum > t.sum;
    }
};
int mp[N][N], ans, n, m, x, y, xx, yy;
int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
bool book[N][N];
char st;
void bfs(int x, int y)
{
    priority_queue<node > q;
    q.push({x, y, 0});
    book[x][y] = true;
    while (!q.empty())
    {
        auto tt = q.top(); q.pop();
        if (tt.x == xx && tt.y == yy)
        {
            ans = tt.sum;
            return;
        }
        for (int k = 0; k < 4; k ++)
        {
            int nx = tt.x + dir[k][0];
            int ny = tt.y + dir[k][1];
            if (nx < 1 || nx > n || ny < 1 || ny > m || book[nx][ny])
              continue;
            book[nx][ny] = true;
            q.push({nx, ny, tt.sum + mp[nx][ny]});
        }
    }
    return;
}
int main()
{
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++)
        {
            cin >> st;
            if (isdigit(st))
              mp[i][j] = st - '0';
            else if (st == 'A' || st == 'B' || st == 'C')
                mp[i][j] = 100;
            else if (st == 'S')
                x = i, y = j;
            else if (st == 'E')
                xx = i, yy = j;;
        }
    book[x][y] = true;
    bfs(x, y);
    cout << ans << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/aezakmias/article/details/107664052