有一个6*6的棋盘,每个棋盘上都有一个数值,现在又一个起始位置和终止位置,请找出一个从起始位置到终止位置代价最小的路径: 1、只能沿上下左右四个方向移动 2、总代价是没走一步的代价之和 3、每步(从a,b到c,d)的代价是c,d上的值与其在a,b上的状态的乘积 4、初始状态为1 每走一步,状态按如下公式变化:(走这步的代价%4)+1。
-
输入描述:
每组数据一开始为6*6的矩阵,矩阵的值为大于等于1小于等于10的值,然后四个整数表示起始坐标和终止坐标。
-
输出描述:
输出最小代价
果然NK就可以为所欲为,感觉dfs太耗时可能过不了,结果也是过了,ԾㅂԾ,,这道题的代价有点启发式,导致虽然知道始末位置但是不能双向bfs。这个启发式的思想导致了使用最短路的算法特别是迪杰斯特拉容易陷入误区,因为最短路算法是按照路径最短来向外扩展的,但是这道题里有着状态的限制,贪心的选择当前路径最短的值有可能使得结果不是最优。所以还是怪怪的枚举状态吧
先放一个spfa WA的代码“
ll m[MAX][MAX], vis[MAX][MAX], dist[MAX][MAX], state[MAX][MAX];
ll dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
ll sx, sy, tx, ty;
struct P {
ll x, y;
P(ll xx = 0, ll yy = 0) { x = xx, y = yy; }
};
bool check(ll x, ll y) {
if (x < 6 && x >= 0 && y < 6 && y >= 0)return true;
return false;
}
ll bfs() {
for (int i = 0; i < 6; i++)for (int j = 0; j < 6; j++)dist[i][j] = inf;
queue<P>q;
q.push(P(sx, sy)); vis[sx][sy] = 1; dist[sx][sy] = 0; state[sx][sy] = 1;
while (!q.empty()) {
P t = q.front(); q.pop(); vis[t.x][t.y] = 0;
if (t.x == tx && t.y == ty)continue;
for (int i = 0; i < 4; i++) {
ll xx = t.x + dx[i], yy = t.y + dy[i];
if (check(xx, yy) && dist[xx][yy] > dist[t.x][t.y] + m[xx][yy] * state[t.x][t.y]) {
dist[xx][yy] = dist[t.x][t.y] + m[xx][yy] * state[t.x][t.y];
state[xx][yy] = (m[xx][yy] * state[t.x][t.y]) % 4 + 1;
if (!vis[xx][yy]) {
q.push(P(xx, yy)); vis[xx][yy] = 1;
}
}
}
}
return dist[tx][ty];
}
int main() {
for (int i = 0; i < 6; i++)for (int j = 0; j < 6; j++)cin >> m[i][j];
cin >> sx >> sy >> tx >> ty;
cout << bfs() << endl;
}
底下是AC的dfs
ll m[MAX][MAX], vis[MAX][MAX], res = inf;
ll dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
ll sx, sy, tx, ty;
struct P {
ll x, y;
P(ll xx = 0, ll yy = 0) { x = xx, y = yy; }
};
bool check(ll x, ll y) {
if (x < 6 && x >= 0 && y < 6 && y >= 0 && !vis[x][y])return true;
return false;
}
void dfs(ll x, ll y, ll cost, ll state) {
if (x == tx && y == ty) {
if (cost < res)res = cost; return;
}
for (int i = 0; i < 4; i++) {
ll xx = dx[i] + x, yy = dy[i] + y;
if (check(xx, yy)) {
vis[xx][yy] = 1;
dfs(xx, yy, cost + state * m[xx][yy], state*m[xx][yy] % 4 + 1);
vis[xx][yy] = 0;
}
}
return;
}
int main() {
for (int i = 0; i < 6; i++)for (int j = 0; j < 6; j++)cin >> m[i][j];
cin >> sx >> sy >> tx >> ty;
dfs(sx, sy, 0, 1);
cout << res << endl;
}