小S练跑步
题目大意
给出一个 行 列的矩阵,求从 到 途中最少要改变几次方向。
每一个点上有一个字母,分别表示:
- ,到这个点后不能向上移动;
- ,到这个点后不能向下移动;
- ,到这个点后不能向左移动;
- ,到这个点后不能向右移动;
- ,到这个点后无法移动。
解题思路
显然是一道最短路,维护方向的转头次数。
记 ,表示从 方向到 最少的转头次数。
其他就都是模板了。
特别要注意一种特殊情况,到 后若 上的字母是 ,那也算一种方法。
AC CODE
#include<bits/stdc++.h>
using namespace std;
const int INF = INT_MAX;
int n, m;
int a[1005][1005];
int ans = INF;
int fx[4][2] = {-1, 0, 1, 0, 0, -1, 0, 1};
int vis[1005][1005][4];
int dis[1005][1005][4];
char getc()
{
char c = getchar();
while(c < 'A' || c > 'Z') c = getchar();
return c;
}
struct abc
{
int x, y, FX;
};
queue<abc> q;
signed main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= m; ++j)
{
char c;
c = getc();
if(c == 'U')
{
a[i][j] = 1;
}
if(c == 'D')
{
a[i][j] = 2;
}
if(c == 'L')
{
a[i][j] = 3;
}
if(c == 'R')
{
a[i][j] = 4;
}
if(c == 'S')
{
a[i][j] = 5;
}
}
}
// memset(dis, INF, sizeof dis);
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= n; ++j)
{
for(int k = 0; k < 4; ++k)
{
dis[i][j][k] = INF;
}
}
}
q.push({1, 1, 3});
q.push({1, 1, 1});
vis[1][1][1] = 1;
vis[1][1][3] = 1;
dis[1][1][1] = 0;
dis[1][1][3] = 0;
while(!q.empty())
{
abc now = q.front();
q.pop();
int x = now.x, y = now.y, FX = now.FX;
vis[x][y][FX] = 0;
if(a[x][y] == 5) continue;
for(int i = 0; i < 4; ++i)
{
if(a[x][y] == 1 && i == 0) continue;
if(a[x][y] == 2 && i == 1) continue;
if(a[x][y] == 3 && i == 2) continue;
if(a[x][y] == 4 && i == 3) continue;
int xx = x + fx[i][0], yy = y + fx[i][1];
if(xx < 1 || xx > n || yy < 1 || yy > m) continue;
if(dis[x][y][FX] + (FX != i) < dis[xx][yy][i])
{
dis[xx][yy][i] = dis[x][y][FX] + (FX != i);
if(!vis[xx][yy][i])
{
q.push({xx, yy, i});
vis[xx][yy][i] = 1;
}
}
}
}
for(int i = 0; i < 4; ++i)
{
ans = min(ans, dis[n][m][i]);
}
if(ans < INF)
{
printf("%d\n", ans);
}
else
{
printf("No Solution\n");
}
return 0;
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18122119