牛客算法周周练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;
}