試題 算法訓練 A Dicey Problem
資源限制
時間限制:1.0s 內存限制:256.0MB
問題描述
圖1中3*3的網格是一個骰子地圖。 一個標準的六面骰子需要在地圖上移動(圖2是一個標準六面骰子的展開圖)。 每張地圖有一個規定的初始位置和一個初始的骰子放置方式。在圖1中,初始位置是第一行第二列——寫着“2”的位置。假設你從地圖的底邊上觀察,骰子的初始放置方式是底面(貼在地圖上的那一面)是”2”,頂面(與底面相對的那一面)是“5”,”1”面向你。
你可以通過沿着骰子的一條邊轉動來將它移動到地圖上水平或是豎直方向上相鄰的格子上。假設當前骰子頂面的數字爲x,那麼你只能將它移動到寫着x的格子上,或者畫着星星圖案的格子上。我們的最終目標是找到一條路徑,使得骰子能從起點出發,最後又回到起點。
舉個例子,在圖1所示的地圖中,一開始你有兩種可行的移動方式——向下或者向左。由於此時骰子頂面所示的數字爲”5”,當前格子下方的格子上寫的數字也是”5”,因此向下移動骰子是可行的;因爲當前位置左邊的格子畫着星星圖案,因此向左移動是可行的。如果第一步選擇向下移動,那麼骰子朝上一面的圖案會變成”6”,此時你可以向右或者向下移動骰子。如果第一步選擇向左移動,那麼骰子頂面的數字會變成3,這種情況下,任何移動方式都是不可行的。
我們用 (行號, 列號) 的方式來標記格子。行號從1開始,從上向下遞增;列號從1開始,從左向右遞增。這樣,在上述例子中一個可行的解可以表示爲:(1,2), (2,2), (2,3), (3,3), (3,2), (3,1), (2,1), (1,1), (1,2)。圖3中展示了一個更加困難的例子。
在本題中,你需要編寫程序對輸入中給定的地圖進行求解。每張地圖可能存在一個唯一的解或者無解。也就是說,對於某一張地圖,如果有解,你可以認爲它只有一個解。對於每張地圖,你需要輸出一解或者一個信息表示無解。
輸入格式
第一行包含6個用空格分隔的整數R, C, x0, y0, T, F,分別表示地圖的行數、列數、初始位置行號、初始位置列號、初始狀態下頂面的數字、初始狀態下面向你的數字。
接下來的R行,每行包含C個空格分隔的整數,定義了這個地圖。如果某個數是0,則表示對應的格子爲空(不可以被走到);如果某個數是-1,則表示對應單元格是畫着星星圖案的單元格;其餘情況下,這個數表示對應格子上寫的數字。
輸出格式
若該地圖無解,則輸出一行“No Solution Possible” (不包含引號)。否則,你應該輸出一個逗號分隔的位置序列,表示骰子依次經過的位置。注意你輸出的第一個位置和最後一個位置應該是相同的(起始位置已在輸入中規定),位置的格式如上文所示。除了最後一行外,每行應該包含九個位置。另外你的輸出中不應包含空格。
樣例輸入
3 3 1 2 5 1
-1 2 4
5 5 6
6 -1 -1
樣例輸出
(1,2),(2,2),(2,3),(3,3),(3,2),(3,1),(2,1),(1,1),(1,2)
樣例輸入
4 7 2 6 3 6
6 4 6 0 2 6 4
1 2 -1 5 3 6 1
5 3 4 5 6 4 2
4 1 2 0 3 -1 6
樣例輸出
(2,6),(2,5),(2,4),(2,3),(2,2),(3,2),(4,2),(4,1),(3,1),
(2,1),(2,2),(2,3),(2,4),(2,5),(1,5),(1,6),(1,7),(2,7),
(3,7),(4,7),(4,6),(3,6),(2,6)
樣例輸入
3 3 1 1 2 4
2 2 3
4 5 6
-1 -1 -1
樣例輸出
No Solution Possible
數據規模和約定
20%的數據,R*C≤30
100%的數據,R,C≤10,保證初始狀態合法。
實現代碼
#include<iostream>
#include<string>
#include<queue>
#include<map>
#include<cstring>
using namespace std;
const int maxn = 11;
// vis存在座標(r, c)處骰子的狀態(上面和前面)是否訪問過。
int maxc, maxr, m[maxn][maxn], vis[maxn][maxn][7][7];
//逆時針存top面是行標爲i時的側面4個點數
int a[7][4] = { {0,0,0,0} ,{2,4,5,3}, {6,4,1,3}, {6,2,1,5}, {6,5,1,2}, {6,3,1,4}, {2,3,5,4} };
string num_to_str(int num) { //數字轉爲字符串
string str = "";
while (num) {
char a = '0' + num % 10;
str = a + str;
num /= 10;
}
return str;
}
struct Node{
map<string, int> face; //存放每一面存放的點數
string str;
int r, c, cnt;
Node(int x, int y, string par_str, map<string, int> a, int new_cnt) {
r = x, c = y, cnt = new_cnt;
if (cnt) {
par_str += ",";
if (cnt % 9 == 0) par_str += "\n"; // 每9個隔一行
}
str = par_str + "(" + num_to_str(r) + "," + num_to_str(c) + ")";
face = a;
}
string get_str() { return str; }
};
map<string, int> turn_down(map<string, int> a) { //向下轉動
int tmp = a["top"];
a["top"] = a["back"];
a["back"] = a["down"];
a["down"] = a["front"];
a["front"] = tmp;
return a;
}
map<string, int> turn_up(map<string, int> a) { //向上轉動
int tmp = a["top"];
a["top"] = a["front"];
a["front"] = a["down"];
a["down"] = a["back"];
a["back"] = tmp;
return a;
}
map<string, int> turn_left(map<string, int> a) { //向左轉動
int tmp = a["top"];
a["top"] = a["right"];
a["right"] = a["down"];
a["down"] = a["left"];
a["left"] = tmp;
return a;
}
map<string, int> turn_right(map<string, int> a) { //向右轉動
int tmp = a["top"];
a["top"] = a["left"];
a["left"] = a["down"];
a["down"] = a["right"];
a["right"] = tmp;
return a;
}
void bfs(int x, int y, int t, int f) {
queue<Node> q;
map<string, int> face;
face["top"] = t, face["down"] = 7 - t;
face["front"] = f, face["back"] = 7 - f;
for (int i = 0; i < 4; i++) {
if (a[t][i] == f) {
face["left"] = a[t][(i + 1) % 4], face["right"] = a[t][(i + 3) % 4];
break;
}
}
memset(vis, 0, sizeof(vis));
q.push(Node(x, y,"", face, 0));
while (q.size()) {
Node now = q.front(); q.pop();
int r = now.r, c = now.c, top = now.face["top"], front = now.face["front"], cnt = now.cnt;
if (vis[r][c][top][front]) continue;
vis[r][c][top][front] = 1;
string str = now.get_str();
if (r == x && c == y) {
vis[r][c][top][front] = 0; //起點不用記錄,只要可以回到就可以了
if (cnt) { //步長不爲0就是重新回到
cout << str;
exit(0);
}
}
if (m[r][c - 1] == top || m[r][c - 1] == -1) { q.push(Node(r, c - 1, str, turn_left(now.face), cnt + 1)); } // left
if (m[r][c + 1] == top || m[r][c + 1] == -1) { q.push(Node(r, c + 1, str, turn_right(now.face), cnt + 1)); } // right
if (m[r - 1][c] == top || m[r - 1][c] == -1) { q.push(Node(r - 1, c, str, turn_up(now.face), cnt + 1)); } // up
if (m[r + 1][c] == top || m[r + 1][c] == -1) { q.push(Node(r + 1, c, str, turn_down(now.face), cnt + 1)); } // down
}
cout << "No Solution Possible" << endl;
}
int main() {
int x, y, t, f;
cin >> maxr >> maxc >> x >> y >> t >> f;
for (int i = 1; i <= maxr; i++) for (int j = 1; j <= maxc; j++) cin >> m[i][j];
bfs(x, y, t, f);
return 0;
}