AOJ0198 Trouble in Artist Shinagawa's Artifact
問題リンク Trouble in Artist Shinagawa's Artifact
- 解法
2つのサイコロが同じものであるかをチェックできるかがカギです。
1つのサイコロは転がしたりすることで24種類の状態を持ちます。
あとは頑張って調べます。
- ソース
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Scanner; //Trouble in Artist Shinagawa's Artifact public class AOJ0198 { 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; } @Override public boolean equals(Object o) { if(!(o instanceof Dice<?>))return false; @SuppressWarnings("unchecked") Dice<T> d = (Dice<T>)o; for(Face f : Face.values()){ if(!id[f.ordinal()].equals(d.id[f.ordinal()])){ return false; } } return true; } boolean isEquivalent(Dice<T> d) { for(int i=0; i<6; i++) { for(int j=0; j<4; j++) { if(this.equals(d)) return true; rollZ(false); } if(i%2==1) rollY(false); else rollX(false); } return false; } 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; } @Override public int hashCode() { int hash = 31; for(Face f : Face.values()){ hash += hash*17+id[f.ordinal()].hashCode(); } return hash; } } @SuppressWarnings("unchecked") public static void main(String[] args) { Scanner sc = new Scanner(System.in); while(true){ int n = sc.nextInt(); if(n==0)break; Dice<String>[] d = new Dice[n]; for(int i=0;i<n;i++){ String[] s = new String[6]; for(int j=0;j<6;j++)s[j]=sc.next(); d[i] = new Dice<String>(s[0],s[5],s[1],s[4],s[2],s[3]); } int c = 0; boolean[] u = new boolean[n]; Arrays.fill(u, true); for(int i=0;i<n;i++){ if(u[i]){ c++; for(int j=i+1;j<n;j++){ boolean f = true; for(Dice<String> t:d[j].getAllState())if(d[i].equals(t)){f = false;break;} if(!f)u[j]=false; } } } System.out.println(n-c); } } }