【デイリーブルーブリッジ】46.2017州大会ジャワグループリアル質問「マジックキューブステート」

こんにちは、私は小さな灰色の類人猿で、バグを書くことができるプログラマーです!

私のコラム「DailyBlueBridge」に注目してください。このコラムの主な機能は、近年のBlue Bridge Cup州の大会や決勝戦の本当の質問を共有し、アルゴリズムのアイデア、データ構造などを分析することです。その中に存在し、あなたが学ぶのを助けるコンテンツより多くの知識と技術に!

タイトル:ルービックキューブのステータス

二次ルービックキューブは、2層のみのルービックキューブで、8つの小さなピースのみで構成されています。

図pl.pngに示すように。

シャオミンはとてもやんちゃで、3色しか好きではないので、自宅で2次ルービックキューブを次のように塗り直しました。

フロント:オレンジ

右:緑

上:黄色

左:緑

下:オレンジ

戻る:黄色

そのようなルービックキューブが破壊された後、いくつの異なる状態があるかを計算してください。

ルービックキューブの全体的な回転後に2つの状態が同じである場合、すべての辺の色が同じである場合、それは同じ状態と見なされます。

州の数を表す整数を提出してください。冗長な内容や説明文は記入しないでください。

問題解決のアイデア:

この質問では、主に候補者の空間的思考と論理的想像力を調べます。解決策は、主に各魔法の立方体をシミュレートすることです。質問の魔法の立方体は8つの小さな立方体で構成され、各立方体には6つの面があります。文字列を使用してこの6つの面を分割します。が表現され、各面の回転過程がシミュレートされ、回転中に各面の変化が記録され、対応する文字列が記録され、文字シーケンスが同じであるため、異なる回転を取得できます。状態今。

回答のソースコード:


import java.util.HashSet;
public class Year2017_Bt4 {
  static char[][] start = {"oybbgb".toCharArray(),
      "oygbbb".toCharArray(),
      "bygbby".toCharArray(),
      "bybbgy".toCharArray(),
      "obbogb".toCharArray(),
      "obgobb".toCharArray(),
      "bbgoby".toCharArray(),
      "bbbogy".toCharArray()};
  static char[][][] q = new char[2000000][8][6];
  static HashSet<String> all_state = new HashSet<String>();
  static int  front, tail;
  static String to_string(char[][] a) {
    String ans = "";
    for (int i = 0; i < 8; ++i) {
      ans += new String(a[i]);
    }
    return ans; 
  }
 
  private static void swap(char[] a, int i, int j) {
    char t = a[i];
    a[i] = a[j];
    a[j] = t;
  }
 
  private static void swap(char[][] a, int i, int j) {
    char[] t = a[i];
    a[i] = a[j];
    a[j] = t;
  }
 
  //上层的块的旋转,面的相对位置调换
  static void ucell(char[] a) {
    swap(a, 0, 2);
    swap(a, 2, 5);
    swap(a, 5, 4);
  }
 
 
  //上层顺时针旋转
  static void u(char[][] s) {
    ucell(s[0]);
    ucell(s[1]);
    ucell(s[2]);
    ucell(s[3]);
//    块的相对位置调换
    swap(s, 1, 0);
    swap(s, 2, 1);
    swap(s, 3, 2);
 
  }
 
  //右层旋转是面的位置变化
  static void rcell(char[] a) {
    swap(a, 1, 0);
    swap(a, 0, 3);
    swap(a, 3, 5);
  }
 
  static void r(char[][] s)//魔方右层顺时针转
  {
    rcell(s[1]);
    rcell(s[2]);
    rcell(s[6]);
    rcell(s[5]);
//    块的位置变化
    swap(s, 2, 1);
    swap(s, 5, 1);
    swap(s, 6, 5);
  }
 
  static void fcell(char[] a) {
    swap(a, 2, 1);
    swap(a, 1, 4);
    swap(a, 4, 3);
  }
 
  static void f(char[][] s)//前面一层 顺时针转
  {
    fcell(s[0]);
    fcell(s[1]);
    fcell(s[4]);
    fcell(s[5]);
    swap(s, 1, 5);
    swap(s, 0, 1);
    swap(s, 4, 0);
  }
 
  static void uwhole(char[][] s)//整个魔方从顶部看 顺时针转 用于判重
  {
    u(s);//上层旋转
//    下层旋转
    ucell(s[4]);
    ucell(s[5]);
    ucell(s[6]);
    ucell(s[7]);
//    完成自旋后,块的位置变动
    swap(s, 5, 4);
    swap(s, 6, 5);
    swap(s, 7, 6);
  }
 
  static void fwhole(char[][] s)//整个魔方从前面看 顺时针转 用于判重
  {
    f(s);
    fcell(s[2]);
    fcell(s[6]);
    fcell(s[7]);
    fcell(s[3]);
    swap(s, 2, 6);
    swap(s, 3, 2);
    swap(s, 7, 3);
  }
 
  static void rwhole(char[][] s)//整个魔方从右边看 顺时针转 用于判重
  {
    r(s);
    rcell(s[0]);
    rcell(s[3]);
    rcell(s[4]);
    rcell(s[7]);
    swap(s, 3, 7);
    swap(s, 0, 3);
    swap(s, 4, 0);
  }
 
 
  static boolean try_insert(char[][] s) {
    char[][] k = new char[8][6];
    memcpy(k, s);
    for (int i = 0; i < 4; i++) {
      fwhole(k);
      for (int j = 0; j < 4; j++) {
        uwhole(k);
        for (int q = 0; q < 4; q++) {
          rwhole(k);
          if (all_state.contains(to_string(k))) {
            return false;
          }
        }
      }
    }
    all_state.add(to_string(k));
    return true;
 
  }
 
  private static void memcpy(char[][] k, char[][] s) {
    for (int i = 0; i < 8; i++) {
      for (int j = 0; j < 6; j++) {
        k[i][j] = s[i][j];
      }
    }
  }
 
  static void solve() {
    front = 0;
    tail = 1;
    all_state.add(to_string(start));
    memcpy(q[front], start);//填充q[0],相当于第一个状态入队列
    while (front < tail) {
        /*将其所有变形,尝试加入set中*/
      memcpy(q[tail], q[front]);//拷贝到tail
      u(q[tail]);//上层顺时针旋转
      if (try_insert(q[tail])) {
        tail++;//扩展队列
      }
      memcpy(q[tail], q[front]);//拷贝到tail
      r(q[tail]);//右层顺时针旋转
      if (try_insert(q[tail])) {
        tail++;//扩展队列
      }
      memcpy(q[tail], q[front]);//拷贝到tail
      f(q[tail]);//前顺时针旋转
      if (try_insert(q[tail])) {
        tail++;//扩展队列
      }
      front++;//弹出队首
//        cout << front << " " << tail << endl;
    }
 
    System.out.println(front);
  }
 
  public static void main(String[] args) {
    solve();
  }
}

サンプル出力:

改善の余地がない、または改善されている分野がありますが、メッセージが小さなパートナーに提示されることを願っています。

興味のある友達はコラムをフォローできます!

リトルグレイエイプが一緒に進歩するためにあなたに同行します!

おすすめ

転載: blog.csdn.net/weixin_44985880/article/details/115278089