题目:这是题目
题意:车轮有五种颜色,每次车子在一个点可以有三种行为,朝着原来方向往前走,或者把车的方向转左或转右,这三个行为都要花费1s时间。车子在起点的车轮颜色是绿色,车头朝上,要求车子到达终点车轮颜色也是绿色,方向可以随意,问是否能到达?能到达最少的时间是多少?
思路:对于每一个格子,要记录5个属性:横坐标、纵坐标、颜色、方向、时间。由于走过的格子是可以再走的,所以我们用一个4维数组记录一个格子,一种颜色和一个方向的所花的最短时间。然后是方向的问题,要么当前方向,要么左转和右转,具体方向的处理见图:
如果当前方向为turn,那么左转和右转方向分别为(turn + 3) % 4 和(turn + 1) % 4。
实现:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <math.h>
using namespace std;
const int MAX = 30;
const int INF = 0x3f3f3f3f;
char _map[MAX][MAX];
int d[MAX][MAX][6][4];//记录到一点一种颜色一个方向的最短路 0green 1white 2blue 3red 4black
int x[4] = {-1, 0, 1, 0};
int y[4] = {0, 1, 0, -1};
int m, n;
int sx, sy, ex, ey;
int ti;
struct node {
int xi, yi, color, turn, time;
};
bool bfs() {
queue <node> q;
node start;
start.xi = sx;
start.yi = sy;
start.color = 0;
start.time = 0;
start.turn = 0;
d[sx][sy][start.color][0] = 0;
q.push(start);
while (!q.empty()) {
node head, tail;
head = q.front();
q.pop();
if (head.xi == ex && head.yi == ey && head.color == 0) {
ti = head.time;
return true;
}
for (int i = 0; i < 3; i++) {
if (i == 0) {
int xx = head.xi + x[head.turn];
int yy = head.yi + y[head.turn];
if (xx >= 0 && xx < m && yy >= 0 && yy < n && _map[xx][yy] != '#'
&& d[xx][yy][(head.color + 1)%5][head.turn] > head.time + 1) {//记录当前这个格子的该颜色的该方向的时间是否比上一步走到这长,长则更新
tail.xi = xx;
tail.yi = yy;
tail.turn = head.turn;
tail.time = head.time + 1;
tail.color = (head.color + 1)%5;
d[xx][yy][tail.color][tail.turn] = tail.time;
q.push(tail);
}
}
else if (i == 1) {
int xx = head.xi;
int yy = head.yi;
if (xx >= 0 && xx < m && yy >= 0 && yy < n && _map[xx][yy] != '#'
&& d[xx][yy][head.color][(head.turn + 3) % 4] > head.time + 1) {//<span style="font-family: Arial, Helvetica, sans-serif;">记录当前这个格子的该颜色的向左方向的时间是否比上一步走到这长,长则更新</span>
tail.xi = xx;
tail.yi = yy;
tail.turn = (head.turn + 3) % 4;
tail.color = head.color;
tail.time = head.time + 1;
d[xx][yy][tail.color][tail.turn] = tail.time;
q.push(tail);
}
}
else if (i == 2) {
int xx = head.xi;
int yy = head.yi;
if (xx >= 0 && xx < m && yy >= 0 && yy < n && _map[xx][yy] != '#'
&& d[xx][yy][head.color][(head.turn + 1) % 4] > head.time + 1) {//<span style="font-family: Arial, Helvetica, sans-serif;">记录当前这个格子的该颜色的向右方向的时间是否比上一步走到这长,长则更新</span>
tail.xi = xx;
tail.yi = yy;
tail.turn = (head.turn + 1) % 4;
tail.color = head.color;
tail.time = head.time + 1;
d[xx][yy][head.color][tail.turn] = tail.time;
q.push(tail);
}
}
}
}
return false;
}
int main() {
int co = 0;
while (scanf("%d%d", &m, &n) != EOF) {
if (m == 0 && n == 0)
break;
co++;
for (int i = 0; i < m; i++)
scanf("%s", _map[i]);
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (_map[i][j] == 'S') {
sx = i;
sy = j;
}
else if (_map[i][j] == 'T') {
ex = i;
ey = j;
}
for (int k = 0; k < 5; k++) {
for (int kk = 0; kk < 4; kk++)
d[i][j][k][kk] = INF;
}//初始化
}
}
if (co != 1) {
printf("\n");
}
printf("Case #%d\n", co);
if (bfs()) {
printf("minimum time = %d sec\n", ti);
}
else {
printf("destination not reachable\n");
}
}
return 0;
}