9

3x1 と 4.5x1 のブロックからパネルを作成する必要があるプロジェクトがあります。構造上の完全性を確保するために、ブロック間のスペースが隣接する列に並ばないようにする必要があります。考えられるすべての組み合わせを計算する必要があります。いくつかの例として、7.5x1 パネルには 2 つの可能なソリューションがあり、7.5x2 パネルには 2 つの可能なソリューションがあり、12x3 パネルには 4 つの可能なウェイがあり、27x5 には 7958 の可能なウェイがあります。私の問題は、幅が広くなると、必要以上の解決策が得られることです。これは、テーブルが重複している可能性があることに関係していると思いますが、それがどこで発生しているのか、またはそれを修正する方法がわかりません。どんな助けでも大歓迎です。コードは以下のとおりです。

import java.util.ArrayList;
import java.util.List;

import puzzle.Row;

public class panel {
/**
 * This program will return the number of unique tables that for structural      integrity don't have blocks that line up
 * in adjacent rows.  The width is to be between 3 and 48 and the height between 1 and 10.  The width
 * should also be a multiple of 0.5.
 * 
 * @param width, height
 * @return totalTables
 */
public static void main(String[] args) {
    int width = 0;
    int height = 0;

    // Check to make sure that two arguments were passed.
    if (args.length != 2) {
        System.out.println("Please enter both a height and a width.");
        System.exit(1);
    } else {
        // Check that a data type of double was entered.
        if ( ( args[0].matches("^[0-9]+(\\.[0-9]+)?$") ) && 
                ( Double.valueOf(args[0].trim()).doubleValue() >= 3.0 ) && 
                ( Double.valueOf(args[0].trim()).doubleValue() <= 48.0 ) && 
                ( Double.valueOf(args[0].trim()).doubleValue()) % 0.5 == 0 ) {
            width = (int) (Double.valueOf(args[0].trim()).doubleValue() * 2); // Double the width so that we are working with an integer.
        } else {
            System.out.println("Please enter a number for your width that is between 3 and 48 and divisable by 0.5.");
            System.exit(1);
        }
        // Check that a data type of integer was entered.
        if ( ( args[1].matches("^[0-9]+$") ) && ( Integer.valueOf(args[1]) >= 1 ) && ( Integer.valueOf(args[1]) <= 10 )) {
            height = Integer.valueOf(args[1].trim()).intValue();
        } else {
            System.out.println("Please enter an integer for your height that is between 1 and 10.");
            System.exit(1);
        }

        List<Row> allRows = new ArrayList<Row>(); // Holds all the possible rows and needed information
        findAllRows(width, 0, 0, allRows);
        findMatches(allRows);
        long totalTables = findUniqueTables(allRows, height);
        System.out.println(totalTables);
    }
}

/**
 * Recursively calculates all possible row combinations for supplied width.
 * Row configuration is stored in binary format with 1 indicating gaps.  Each bit is
 * represented by 3 inches.  The bits 1, 2, nth are dropped as they are not needed.
 * 
 * i.e. width of 12 would produce
 * width = 12 * 2 = 24
 * 
 * Bricks               Binary              Stored Binary   Decimal Value
 * 6 x 6 x 6 x 6        0 1 0 1 0 1 0 1     1 0 1 0 1       21
 * 9 x 9 x 6            0 0 1 0 0 1 0 1     0 1 0 0 1       9
 * 9 x 6 x 9            0 0 1 0 1 0 0 1     0 1 0 1 0       10
 * 6 x 9 x 9            0 1 0 0 1 0 0 1     1 0 0 1 0       18
 */

public static void findAllRows(int width, int currLen, int rowConfig, List<Row> root) {
    if (currLen + 6 == width) {
        root.add(new Row(width, rowConfig)); // Add current row configuration as an acceptable row.
        return;
    } else if (currLen + 9 == width) {
        rowConfig = rowConfig << 1;
        root.add(new Row(width, rowConfig)); // Add current row configuration as an acceptable row.
        return;
    } else if (currLen + 6 > width) {
        return; // Current configuration is longer than the width is allowed.  Do not add.
    } else {
        int nextConfig = (rowConfig << 2) + 1;  //
        findAllRows(width, currLen + 6, nextConfig, root);

        nextConfig = (rowConfig << 3) + 1;
        findAllRows(width, currLen + 9, nextConfig, root);
    }
    return;
}

/**
 * Finds all possible row matches for the given row that do not have gaps that line up.
 */
public static void findMatches(List<Row> rows) {
    for (Row row : rows) {
        for (Row rowC : rows) {
            if (matchesBelow(row.getGaps(), rowC.getGaps())) {
                row.addChilcRows(rowC.getGaps());
            }
        }
    }
}

/**
 * Does a bitwise AND to see if there are any gaps that line up.  If there are no gaps then
 * the resulting AND should equal to 0.
 */
public static boolean matchesBelow(int row, int rows) {
    if ((row & rows) == 0) {
        return true;
    } else {
        return false;
    }
}

/**
 * Finds all the unique tables and returns the count.
 */
public static long findUniqueTables(List<Row> allRows, int height) {
    long tableCount = 0;
    for (Row row : allRows) {
        tableCount += findTables(row, height);
    }
    return tableCount;
}


/**
 * This makes all possible tables.
 */
public static long findTables(Row row, int tableHeight) {
    long count;
    if (tableHeight == 1) {
        return 1;
    } else {
        count = 0;
        for (int i = 0; i < row.getChildRowsSize(row); i++) {
            count += findTables(row, tableHeight -1);
        }   
    }
    return count;
}
}

そして私の puzzle.Row クラス。

package puzzle;

import java.util.ArrayList;
import java.util.List;

public class Row {
int gaps;
int width;
List<Long> potChildRows = new ArrayList<Long>();

public Row(int width, int gaps) {
    this.gaps = gaps;
    this.width = width;
}

public int getGaps() {
    return this.gaps;
}

public int getWidth() {
    return this.width;
}

public long getChildRowsSize(Row row) {
    return row.potChildRows.size();
}

public void addChilcRows(long row) {
    this.potChildRows.add(row);
}
}
4

1 に答える 1

2

課題を解いただけだと思います。質問されてから2か月経ちましたが、解くのが楽しい問題だと思ったので、試してみました。「宿題」タグのために(2か月後でも)コードを投稿したくないので、私のアプローチについて説明します。私は Python を使用しましたが、あらゆる用語を Java に翻訳しようとします。

まず、必要以上のデータを追跡しているように感じます。double の ArrayList を保持し、 doubleiiix1 ブロックを参照するようにしました。リストは、それrow[0]が一番左のブロックでrow[row.length-1]、一番右のブロックになるように並べられました。たとえば、[3, 3, 4.5]左から右に、3x1 ブロック、別の 3x1 ブロック、および 4.5x1 ブロックを使用して、長さ 10.5 の行を参照します。この単純な構造を使用すると、構成を簡単に視覚化できます。私の行の長さは、すべての要素を一緒に追加するのと同じくらい簡単です (つまり3 + 3 + 4.5 = 10.5)。私のギャップは、リストを繰り返しながら実行中の合計を維持するのと同じくらい簡単です (つまり、私のギャップは33 + 3 = 6です)。この単純なデータ型を使用すると、コードを大幅に単純化できます。

また、問題を修正された深さ優先検索と考えると役立つことがわかりました。DFS を使用してバイナリ ツリーを指定すると、最初にルートから始めてすべて左に移動しようとします。次に、最後のノードを 1 つ残してすべて左に移動しようとします。等々。「左」と「右」の代わりに、ノードの値が幅である「3」と「4.5」を考えてください。幅が目的の幅よりも大きくなると、ツリーのトラバースを停止しますwidth。正確に の値を持つノードを見つけた場合width、そのパスは可能な行になりました。それを覚えておいてください。言い換えれば、最初に N 3x1 ブロック ( などwidth + 2.5 >= N*3 >= width) を試して、行を左から右に構築します。次に、(N-1) 3x1 ブロックと 1 つの 4x1 ブロックを試します (4x1 が一番右です)。次に、(N-2) 3x1、1 つの 4x1、およびもう 1 つの 3x1。等々。ビットシフトなし、いいえrowConfig変数、ブロック幅の ArrayList のみ。また、各パスを体系的に移動した (つまり、各組み合わせを試した) のは 1 回だけであるため、すべての組み合わせを試したことがわかり、重複がないことがわかります。

さあ、壁を作りましょう。これは、変更された DFS として扱うこともできます。n が wi​​dth の潜在的な行の数に等しい n 分木を想像してくださいwidth。同じ体系的なアプローチを使用して、高さの壁ができるまですべてのパスを試しますheight(各行の高さが 1 であるため)。ただし、ギャップが隣接していない場合にのみ、パスをトラバースする必要があることを忘れないでください。下から上に向かって、一度に 1 列ずつ壁を構築してみてください。上部の列のギャップに隣接するギャップがない場合にのみ、壁の上部に新しい列を追加することで、部分的な壁が常に有効であると信頼できます。そこで、 をヒットheightすると、有効な壁があることがわかります。パスを記録し、探索する有効なパスがなくなるまで続行します。

あなたがまだ課題をしている間に返事をしなかったことをお詫びします。あなたの最終的な解決策が私のものとどう違うのか知りたいです。

于 2012-06-14T15:10:35.137 に答える