A Dicey Problem 骰子难题(Uva 810)

 

题目描述:https://uva.onlinejudge.org/external/8/810.pdf

把一个骰子放在一个M x N的地图上,让他按照规定滚动,求滚回原点的最短路径。

 


 

 

 

思路:  记忆化搜索(我这里用的dfs深度优先搜索)


 

难点:

如何推导骰子的状态

我没有用打表,而是先用build_dice()初始化二维数组dice, 这样,当我们有骰子的顶面top,正面face, 就可以通过dice[top][face] 获得对应的右面,由此,就可以实现骰子的旋转。rotate()函数实现骰子的旋转,给它top, face, 和旋转的方向(前,后,左,右), 它会返回旋转后骰子的top, face.

          

记忆化搜索要多一个状态记录骰子的状态

说白了就是记录访问状态的数组vis要多两个维度分别记录top, face因为top, face一旦固定,骰子就固定了

 

Note: 输出的格式也要稍微注意一下,锁进、末尾的逗号,换行要处理好。

  

#include <iostream>
#include <cstdio>
#include <vector>
#include <utility>
#include <cstring>
 
using namespace std;
const int MAXN = 10 + 2;
int b[MAXN][MAXN], R, C, sx, sy, st, sf, len;
int dx[] = {0, -1, 0, 1}, dy[] = {1, 0, -1, 0}, dice[7][7];   
bool vis[MAXN][MAXN][7][7], ok, first;
vector<pair<int, int> > path;
 
void build_dice() {             //dice[top][face] = right
    dice[1][2] = 3;
    for (int i = 1; i < 7; i++) {
        for (int j = 1; j < 7; j++) {
            if (i == j) continue;
            if (dice[i][7 - j]) dice[i][j] = 7 - dice[i][7 - j];
            if (dice[i][j]) {
                dice[j][i] = 7 - dice[i][j];
                dice[i][dice[i][j]] = 7 - j;
            }
        }
    }
}
 
pair<int, int> rotate(int top, int face, int di) {
    pair<int, int> n_tf;
    if (di == 0) {
        n_tf.second = face;
        n_tf.first = 7 - dice[top][face];
    }
    else if (di == 1) {
        n_tf.first = face;
        n_tf.second = 7 - top;
    }
    else if (di == 2) {
        n_tf.second = face;
        n_tf.first = dice[top][face];
    }
    else {
        n_tf.second = top;
        n_tf.first = 7 - face;
    }
    return n_tf;
}
 
bool inside(int x, int y) {
    return x > 0 && y > 0 && x <= R && y <= C;
}
 
void dfs(int x, int y, int t, int f) {
    path.push_back(make_pair(x, y));
    if (x == sx && y == sy)
        if (first) first = 0;
        else { ok = 1; return;}
    vis[x][y][t][f] = 1;
     
    for (int i = 0; i < 4; i++) {
        pair<int, int> nextp = rotate(t, f, i);
        int nx = x + dx[i], ny = y + dy[i];
        int nt = nextp.first, nf = nextp.second;
        if (inside(nx, ny) && (!vis[nx][ny][nt][nf] || (nx == sx && ny == sy)) && (t == b[nx][ny] || b[nx][ny] == -1)) {
            dfs(nx, ny, nt, nf);
        }
        if (ok) return;
    }
    vis[x][y][t][f] = 0;
    path.pop_back();
}
 
int main() {
    build_dice();
    char name[25];
    while (scanf("%s", name) == 1 && strcmp(name, "END")) {
        scanf("%d%d%d%d%d%d", &R, &C, &sx, &sy, &st, &sf);
        memset(vis, 0, sizeof(vis));
        memset(b, 0, sizeof(b));
        path.clear(); ok = 0; first = 1;
        for (int i = 1; i <= R; i++)
            for (int j = 1; j <= C; j++)
                scanf("%d", &b[i][j]);
        dfs(sx, sy, st, sf);
        len = path.size();
        printf("%s", name);
        if (ok)
            for (int i = 0; i < len; i++) {
                if (i % 9 == 0) {
                    if (i >= 9) printf(",");
                    printf("\n  (%d,%d)", path[i].first, path[i].second);
                }
                else printf(",(%d,%d)", path[i].first, path[i].second);
            }
        else printf("\n  No Solution Possible");
        printf("\n");
    }
    return 0;
}

 

 

 

转载于:https://www.cnblogs.com/Bowen-/p/4935750.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值