ITP1_11_A
Dice I | Aizu Online Judge
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_11_A
問題は処理の部分
サイコロを一方向に回すとき
4面が動き
2面は固定
Nに1回動くときはSに3回動く
Wに1回動くときはEに3回動く
サイコロの面は配列として考え0-5までに当てはめる。
このプログラムは配列の添字をベースとして考え
動く前と動いたあとの数値を連鎖をさせながら考えている。
0, 1, 5, 4などのマジックワードが出てくるが、
これはサイコロの面の動きを原始的に考えているだけ。
Nに1回動かすと考え(X軸方向)
添字は
0 1 2 3 4 5 (初期値)から
1 5 2 3 0 4 と変化する
ここは紙の出番。
紙上で書きながら考える。
(自分には頭の中だけで考えるのは無理。)
2面と3面は固定しているのがわかる。(変化なし)
動いているのは4面
初期値の動く数字を見ていく
上面の0はtemporary(=一時退避)
0には1を入れる。
1の場所には5を入れる。
5の場所には4を入れる
4の場所には0 (=temporary)を入れる。
トップを一旦退避して、そこに数字を入れ、さらにそこに入れた数字を追いかけていきながら考える。
添字で考えているので6面サイコロならどんな数字でも対応可能。
これをプログラムとして書くと
void roll_x() { roll(0, 1, 5, 4); } // to N
void roll(int i, int j, int k, int l) {
int t = f[i];
f[i] = f[j];
f[j] = f[k];
f[k] = f[l];
f[l] = t;
}
この考えを元にy軸方向とz軸方向でも考える。
Z軸
012345(初期値)
024135(0と5は固定)
Y軸
012345(初期値)
215043(1と4は固定)
void roll_z() { roll(1, 2, 4, 3); }
void roll_y() { roll(0, 2, 5, 3); } // to W
と答えが出る。
参考
オンラインジャッジではじめるC/C++プログラミング入門 p238
# include <bits/stdc++.h>
using namespace std;
class Cube {
public:
int f[6]; //サイコロ
Cube() {} //コンストラクタ
void roll_z() { roll(1, 2, 4, 3); }
void roll_y() { roll(0, 2, 5, 3); } // to W
void roll_x() { roll(0, 1, 5, 4); } // to N
void roll(int i, int j, int k, int l) {
int t = f[i];
f[i] = f[j];
f[j] = f[k];
f[k] = f[l];
f[l] = t;
}
void move(char ch) {
if (ch == 'E')
for (int i = 0; i < 3; i++) roll_y(); // Wを3回
if (ch == 'W') roll_y();
if (ch == 'N') roll_x();
if (ch == 'S')
for (int i = 0; i < 3; i++) roll_x(); // Nを3回
}
};
int main() {
Cube c; // サイコロ
string com; // 命令
// 入力
for (int i = 0; i < 6; i++) cin >> c.f[i]; // サイコロの面
cin >> com; // 命令
// 処理
for (int i = 0; i < com.size(); i++) {
c.move(com[i]);
}
// 出力
cout << c.f[0] << "\n";
return 0;
}
感想
クラスを使うということでプログラミングへの心理的障壁は高かったが、中身を改めて見渡すと中学生でも簡単だと思えるレベルのものだった。
しかし、紙上でサイコロの面を追いかけながらどの数字がどこに入るかを追いかけていくのはかなりの時間がかかってしまった。