题目:
有一个 6×6 的棋盘,棋盘的每个位置上都有一个数值,现在有一个起始位置和终止位置,请找出一个从起始位置到终止位置代价最小的路径:
- 只能沿上下左右四个方向移动。
- 总代价是每走一步的代价之和。
- 每步(从 (a,b) 到 (c,d))的代价是 (c,d) 上的数值与其在 (a,b) 上的状态的乘积。
- 初始状态为 1,每走一步,状态按如下公式变化:((走这步的代价mod4)+1。
输入格式
每组数据一开始为 6×6 的矩阵,然后四个整数表示起始坐标和终止坐标。
横纵坐标均从 0 开始,矩阵的左上角为 (0,0),右下角为 (5,5)。
输出格式
输出最小代价。
数据范围
矩阵内数值的取值范围[1,10]。
输入样例:
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
0 0 5 5
输出样例:
23
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 6;
int w[N][N];//记录每个点的数值
int sx, sy, tx, ty;//起点、终点
int dist[N][N][5];//"[5]"用来记录走到这个点的1-4的状态s的最小值
bool st[N][N][5];
struct Node
{
int x, y, s;
};
int spfa()
{
queue<Node> q;
q.push({sx, sy, 1});
memset(dist, 0x3f, sizeof dist);
dist[sx][sy][1] = 0;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
while (q.size())
{
auto t = q.front();
q.pop();
st[t.x][t.y][t.s] = false;
for(int i = 0; i < 4; i ++)
{
int x =t.x + dx[i], y = t.y + dy[i];
if(x < 0 || x >= N || y < 0 || y >= N) continue;
int cost = t.s * w[x][y];
int s = cost % 4 + 1;
if(dist[x][y][s] > dist[t.x][t.y][t.s] + cost)
{
dist[x][y][s] = dist[t.x][t.y][t.s] + cost;
if(!st[x][y][s])
{
q.push({x, y, s});
st[x][y][s] = true;
}
}
}
}
int res = 1e8;
for(int i = 1; i <= 4; i ++ )
res = min(res, dist[tx][ty][i]);
return res;
}
int main()
{
for(int i = 0; i < N; i ++ )
for(int j = 0; j < N; j ++)
scanf("%d",&w[i][j]);
scanf("%d%d%d%d",&sx, &sy, &tx, &ty);
printf("%d\n",spfa());
return 0;
}