0

2^k * 2^k サイズのボードが与えられましたが、タイルの 1 つがランダムに削除され、欠陥のあるボードになっています。タスクは、3 つのタイルで作られた L 字型の図形である「トロミノ」で埋めることです。

それを解決するプロセスはそれほど難しくありません。ボードが 2x2 の場合、1 つのトロミノだけでボードを埋めることができます。それ以上のサイズの場合は、4 つに分割し (4 つの 2^(k-1) サイズのボードを作成)、中心点に 1 つのトロミノを配置して、各象限に 1 つの塗りつぶされたタイルを配置する必要があります。その後、すべてのタイルがランダムな色のトロミノで満たされるまで、ボードを再帰的に埋めることができます。

私の主な問題は、実際にコードを実装することです。私の Java プログラミングのスキルは概してかなり弱く、単純にどこから始めればよいかを見つけるのに苦労することがよくあります。実行する唯一の作業は、tiling クラスの tile メソッドです。このメソッドは、入力としてタイルへの不足ボード、タイルを開始する行と列、および塗りつぶすタイルの数を受け取ります。これは宿題の問題なので、手引きや開始点を探しているだけです。どんな助けでも大歓迎です。

public class BoardViewer extends JFrame {

private static final int WIDTH = 1024;
private static final int HEIGHT = 768;
private static final int OFFSET = 30;

public static final int UPVERT = 1;
public static final int DNVERT = 2;
public static final int RHORIZ = 4;
public static final int LHORIZ = 8;
public static final int FILL = 16;

private Color [][] board;

public BoardViewer(DeficientBoard db) {
    super();
    setSize(WIDTH + (OFFSET*2), HEIGHT + (OFFSET*2));
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setResizable(false);

    board = db.getBoardColor();
}

public void paint(Graphics g) {
    super.paint(g);

    int width = WIDTH/board[0].length;
    int height = HEIGHT/board.length;

    for (int r = 0; r < board.length; r++)
        for (int c = 0; c < board[r].length; c++) {
            g.setColor(board[r][c]);

            int x = c*width + OFFSET;
            int y = r*height + OFFSET + (OFFSET/2);

            g.fillRect(x+1, y+1, width-1, height-1);
        }
}

}

public class DeficientBoard {

private int n;
private Color board[][];

// The four rotations of the tile.
// UL is XX
//       X
// UR is XX
//        X
// LL is X
//       XX
// LR is  X
//       XX
public final int UL = 0;
public final int UR = 1;
public final int LL = 2;
public final int LR = 3;

/**
 * Create a 2^k x 2^k deficient board.
 * 
 * @param k power
 */
public DeficientBoard(int k) {
    n = (int)Math.pow(2, k);
    createBoard(Color.LIGHT_GRAY);
}

/**
 * Actually create an n x n deficient board.
 * 
 * @param color background color
 */
private void createBoard(Color color) {
    board = new Color[n][n];
    for (int r = 0; r < board.length; r++)
        for (int c = 0; c < board[0].length; c++)
            board[r][c] = color;

    int d_row = (int)(Math.random() * n);
    int d_col = (int)(Math.random() * n);
    board[d_row][d_col] = Color.BLACK;
}

/**
 * Given a row and column and shape based on that point
 * place a tromino of the given color.
 * 
 * @param r row
 * @param c column
 * @param s shape (UL, UR, LL, LR)
 * @param theColor a Color
 */
public void placeTromino(int r, int c, int s, Color theColor) {
    if (s == UL) {
        board[r][c] = theColor; 
        board[r][c+1] = theColor;
        board[r+1][c] = theColor;
    } else if (s == UR) {
        board[r][c] = theColor;
        board[r][c+1] = theColor;
        board[r+1][c+1] = theColor;
    } else if (s == LL) {
        board[r][c] = theColor;
        board[r+1][c] = theColor;
        board[r+1][c+1] = theColor;
    } else {
        board[r+1][c] = theColor;
        board[r+1][c+1] = theColor;
        board[r][c+1] = theColor;
    }
}

/**
 * Get the 2^k x 2^k board.
 * 
 * @return the Color board.
 */
public Color[][] getBoardColor() {
    return board;
}

/**
 * Find and return the deficient row.
 * 
 * @param row row
 * @param col column
 * @param sz size of the baord
 * @return the row the deficient block is located
 */
public int getDeficientRow(int row, int col, int sz) {

    for (int r = row; r < (row + sz); r++)
        for (int c = col; c < (col + sz); c++)
            if (board[r][c] != Color.LIGHT_GRAY)
                return r;

    return -1;
}

/**
 * Find and return the deficient column.
 * 
 * @param row row
 * @param col column
 * @param sz size of the baord
 * @return the row the deficient block is located
 */
public int getDeficientCol(int row, int col, int sz) {
    for (int r = row; r < (row + sz); r++)
        for (int c = col; c < (col + sz); c++)
            if (board[r][c] != Color.LIGHT_GRAY)
                return c;

    return -1;
}

/**
 * Get the size of the deficient board.
 * 
 * @return the size
 */
public int getSize() {
    return n;
}

/**
 * Display information about the deficient board.
 */
public String toString() {
    return ("Deficient board of size " 
             + n + "x" + n
             + " with position missing at (" 
             + getDeficientRow(0, 0, n) + "," + getDeficientCol(0, 0, n) +").");
}

}

public class Tiling {

private static Color randColor() {
    int r = (int)(Math.random() * 256);
    int g = (int)(Math.random() * 256);
    int b = (int)(Math.random() * 256);

    return new Color(r, g, b);
}

public static void tile(DeficientBoard db, int row, int col, int n) {


}

public static void main(String[] args) {

    DeficientBoard db = new DeficientBoard(3);
    System.out.println(db);

    tile(db, 0, 0, db.getSize());

    BoardViewer bv = new BoardViewer(db);
    bv.setVisible(true);

}

}

4

2 に答える 2

1

一般に、再帰関数が分割統治アルゴリズムを実装する場合、次の 2 つの基本的なケースを処理する必要があります。

  • ベースケース。これは、分割が完了し、少し征服する必要がある場合です。あなたの課題では、ベース ケースはn = 2 の場合です。その場合、4 つのタイルのうちどれが欠けているか、またはペイントされているかを見つけ (DefectiveBoard.getDeficientRowとを使用DefectiveBoard.getDeficientCol)、適切なトリオミノを追加して他の 3 つのタイルをカバーする必要があります。
  • 再帰的な場合。これは、除算が完了していない場合です。したがって、除算 (つまり、再帰) が必要であり、(アルゴリズムによっては) 再帰の前または後に少し征服する必要がある場合があります。あなたの割り当てでは、再帰的なケースはn > 2 の場合です。その場合、次の 2 つのことを行う必要があります。
    • 4 つの象限のどれに欠けている/塗装されたタイルがあるかを見つけ、適切なトリオミノを追加して、他の 3 つの象限のそれぞれから 1 つのタイルをカバーします。
    • 繰り返し、自分自身を 4 回呼び出します (各象限に 1 回)。

良い出発点は、「これは基本ケースですか?」と書くことです。チェックし、基本ケースを実装します。

その後、再帰的なケースの書き方がわからない場合は、一時的に「ベースよりも 1 つ上」のケース ( n = 4) を書き、一般化できるかどうかを確認するのも 1 つの方法です。そうでない場合は、一時的に「ベースより 2 つ上」のケース ( n = 8) などを書くことができます。(再帰アルゴリズムが機能するようになったら、一般的な再帰ケースで完全にカバーされるため、これらの特殊なケースを削除します。)

于 2013-02-27T18:46:13.430 に答える
-1

まあ、これは解決するのがやや難しい問題です。しかし、あなたが書いたコードの量を考えると、あなたにはスキルがあると思いますので、私はそれについて意識しません。

完全な解決策は策定されていませんが、削除されたタイルから始めて、その両側にトロミノスを配置すると思います. 次に、最後のトロミノの両側にトロミノを置き続けます。あなたは最後にボードに置いたトロミノを「すくっている」のです。ボードの端までそれをしたら。残っているのは、トロミノ型の場所だけです。以下に例を示します (X はドロップされたタイル、つまりギャップ、Y はトロミノです)。

 _ _ _ _
|_|_|_|_|
|_|Y|Y|_|
|_|Y|X|Y|
|_|_|Y|Y|

 _ _ _ _
|Y|Y|_|_|
|Y|Y|Y|_|
|_|Y|X|Y|
|_|_|Y|Y|

ボードが端までいっぱいになると、ボードの残りの部分に爆弾のようなトロミノを落とし始めることができます。斜めのトロミノを埋めながら、同時に2番目の部分を埋めていくという繰り返し可能なパターンがあるような気がします。しかし、それが見つからない場合は、再帰ルーチンを作成して、ギャップをエッジにスプーンで広げ、対角線パターンでトロミノを追加することに移行します。最初のスタック フレームでのみトランジションを実行する必要があるというヒントがあります。

幸運を。

于 2013-02-27T04:14:04.660 に答える