AOJ1181 Biased Dice

問題リンク Biased Dice

  • 解法

サイコロのシミュレート問題です。
h[i][j]: 座標(i, j)に積み重なっているサイコロの数
state[i][j]: 座標(i, j)の一番上にあるサイコロの上の面の数字
これらの状態を管理すればデータは十分です。サイコロの動かし方はライブラリがあると楽ですが、無ければ頑張るしかないですね。

  • ソース
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

//Biased Dice
public class AOJ1181 {

	public static class Dice <T>{
		public T[] id;
		enum Face{TOP, BOTTOM, FRONT, BACK, RIGHT, LEFT};
		public T get(Face f){
			return id[f.ordinal()];
		}
		public Dice<T> copy(){
			return new Dice<T>(id[0], id[1], id[2], id[3], id[4], id[5]);
		}
		public Dice() {
			@SuppressWarnings("unchecked")
			T[] tid = (T[])new Object[6];
			id = tid;
		}
		public Dice(T top, T bottom, T front, T back, T right, T left) {
			@SuppressWarnings("unchecked")
			T[] tid = (T[])new Object[6];
			id = tid;
			id[Face.TOP.ordinal()] = top;
			id[Face.BOTTOM.ordinal()]= bottom;
			id[Face.FRONT.ordinal()] = front;
			id[Face.BACK.ordinal()] = back;
			id[Face.RIGHT.ordinal()] = right;
			id[Face.LEFT.ordinal()] = left;
		}
		//true: X軸方向に手前に転がす
		//false: X軸方向に奥に転がす
		void rollX(boolean isReverse) {
			if(!isReverse) roll(Face.TOP, Face.FRONT, Face.BOTTOM, Face.BACK);
			else roll(Face.TOP, Face.BACK, Face.BOTTOM, Face.FRONT);
		}
		//true: Y軸方向に左へ転がす
		//false: Y軸方向に右へ転がす
		void rollY(boolean isReverse) {
			if(!isReverse) roll(Face.TOP, Face.LEFT, Face.BOTTOM, Face.RIGHT);
			else roll(Face.TOP, Face.RIGHT, Face.BOTTOM, Face.LEFT);
		}
		//true: Z軸方向に右へ回す
		//false: Z軸方向に左へ回す
		void rollZ(boolean isReverse) {
			if(!isReverse) roll(Face.FRONT, Face.LEFT, Face.BACK, Face.RIGHT);
			else roll(Face.FRONT, Face.RIGHT, Face.BACK, Face.LEFT);
		}
		private void roll(Face w, Face x, Face y, Face z) {
			T tmp = id[w.ordinal()];
			id[w.ordinal()] = id[x.ordinal()];
			id[x.ordinal()] = id[y.ordinal()];
			id[y.ordinal()] = id[z.ordinal()];
			id[z.ordinal()] = tmp;
		}
		List<Dice<T>> getAllState(){
			List<Dice<T>> lst = new ArrayList<Dice<T>>();
			for(int i = 0; i < 6; i++){
				for(int j = 0; j < 4; j++){
					lst.add(new Dice<T>(id[Face.TOP.ordinal()], id[Face.BOTTOM.ordinal()], id[Face.FRONT.ordinal()], id[Face.BACK.ordinal()], id[Face.RIGHT.ordinal()], id[Face.LEFT.ordinal()]));
					rollZ(false);
				}
				if(i%2 == 1) rollY(false);
				else rollX(false);
			}
			return lst;
		}
	}

	List<Dice<Integer>> dice;

	int get(int t, int f){
		for(int i=0;i<24;i++){
			Dice<Integer> d = dice.get(i);
			if(d.get(Dice.Face.TOP)==t && d.get(Dice.Face.FRONT)==f)return i;
		}
		return -1;
	}
	
	void run(){
		Dice<Integer> o = new Dice<Integer>(1, 6, 3, 4, 5, 2);
		dice = o.getAllState();
		Scanner sc = new Scanner(System.in);
		for(;;){
			int n = sc.nextInt();
			if(n==0)break;
			int[][] h = new int[20][20], state = new int[20][20];
			for(int i=0;i<n;i++){
				int t = sc.nextInt(), f = sc.nextInt();
				Dice<Integer> d = dice.get(get(t, f));
				int pi = 10, pj = 10;
				for(;;){
					boolean con = false;
					for(int num=6;num>=4;num--){
						if(d.get(Dice.Face.FRONT)==num){
							if(h[pi+1][pj] < h[pi][pj]){
								Dice<Integer> copy = d.copy();
								copy.rollX(true);
								pi++;
								d = copy;
								con = true;
								break;
							}
						}
						else if(d.get(Dice.Face.BACK)==num){
							if(h[pi-1][pj] < h[pi][pj]){
								Dice<Integer> copy = d.copy();
								copy.rollX(false);
								pi--;
								d = copy;
								con = true;
								break;
							}
						}
						else if(d.get(Dice.Face.RIGHT)==num){
							if(h[pi][pj+1] < h[pi][pj]){
								Dice<Integer> copy = d.copy();
								copy.rollY(false);
								pj++;
								d = copy;
								con = true;
								break;
							}
						}
						else if(d.get(Dice.Face.LEFT)==num){
							if(h[pi][pj-1] < h[pi][pj]){
								Dice<Integer> copy = d.copy();
								copy.rollY(true);
								pj--;
								d = copy;
								con = true;
								break;
							}
						}
					}
					if(!con){
						h[pi][pj]++; state[pi][pj] = d.get(Dice.Face.TOP);
						break;
					}
				}
			}
			int[] c = new int[7];
			for(int i=0;i<20;i++)for(int j=0;j<20;j++)c[state[i][j]]++;
			for(int i=1;i<7;i++)System.out.print(c[i]+(i==6?"\n":" "));
		}
	}

	public static void main(String[] args) {
		new AOJ1181().run();
	}
}