UVA 10047--The Monocycle

题目:这是题目


题意:车轮有五种颜色,每次车子在一个点可以有三种行为,朝着原来方向往前走,或者把车的方向转左或转右,这三个行为都要花费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;
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值