私は再帰を学習していますが、アルゴリズムの作成を開始する方法についての参考文献が必要です。私はボードの可能な最大の充填で、すべての部分を使用するブロックを整理する必要があります。ありがとうございます。要素(テトリスの一部)を再帰的に編成する方法
0
A
答えて
1
ここでは、始めに役立つこのアルゴリズムのかなり単純な実装です。
完璧なソリューション(ボードが完全に埋め込まれている場所)を探していて、見つかるとすぐに終了します。これはあなたのサンプルボードに期待どおりに動作しますが、単純な完璧な解決策を持たない他のボードや完全な解決策がまったくなくても、永久に動くことがあります。
優れたアルゴリズムになります。すべてのボードに最適なソリューションのための
- ルック検索
だけ洗練をスピードアップするために(だけでなく、完璧なもの)
ボードの各行はバイトとして表され、各部分は2x2ビットとして表されます。
var b = [
// initial board
0b00000000,
0b00000000,
0b00000100,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
],
piece = [
// bitmasks of pieces as [ top_bitmask, bottom_bitmask ]
[ 0b11, 0b01 ], [ 0b11, 0b10 ], [ 0b01, 0b11 ], [ 0b10, 0b11 ]
],
// hash table of visited boards
hash = {},
// statistics
node = 0, hit = 0;
function solve(sol) {
var x, y, p, s;
// compute hexadecimal key representing the current board
var key =
((b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)) >>> 0).toString(16) + '-' +
((b[4] | (b[5] << 8) | (b[6] << 16) | (b[7] << 24)) >>> 0).toString(16);
node++;
if(hash[key]) {
// abort immediately if this board was already visited
hit++;
return false;
}
if(key == 'ffffffff-ffffffff') {
// return the current solution if the board is entirely filled
return sol;
}
// save board in hash table
hash[key] = true;
// for each position and each type of piece ...
for(y = 0; y < 7; y++) {
for(x = 0; x < 7; x++) {
for(p = 0; p < 4; p++) {
// ... see if we can insert this piece at this position
if(!(b[y] & (piece[p][0] << x)) && !(b[y + 1] & (piece[p][1] << x))) {
// make this move
b[y] ^= piece[p][0] << x;
b[y + 1] ^= piece[p][1] << x;
// add this move to the solution and process recursive call
s = solve(sol.concat(x, y, p));
// unmake this move
b[y] ^= piece[p][0] << x;
b[y + 1] ^= piece[p][1] << x;
// if we have a solution, return it
if(s) {
return s;
}
}
}
}
}
return false;
}
function display(sol) {
var n, x, y, html = '';
for(n = 0; n < 64; n++) {
html += '<div class="cell"></div>';
}
$('#container').html(html);
for(n = 0; n < sol.length; n += 3) {
for(y = 0; y < 2; y++) {
for(x = 0; x < 2; x++) {
if(piece[sol[n + 2]][y] & (1 << x)) {
$('.cell').eq(7 - sol[n] - x + (sol[n + 1] + y) * 8)
.addClass('c' + sol[n + 2]);
}
}
}
}
}
setTimeout(function() {
display(solve([]));
console.log(node + ' nodes visited');
console.log(hit + ' hash table hits');
}, 500);
#container { width:160px; height:160px }
.cell { width:19px; height:19px; margin:1px 1px 0 0; background-color:#777; float:left }
.c0 { background-color:#fb4 }
.c1 { background-color:#f8f }
.c2 { background-color:#4bf }
.c3 { background-color:#4d8 }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">Searching...</div>
1
再帰は、次の2つの主要なアイデアを持って、最初はそれぞれの問題をステップということである(ので、この場合はボード)あなたが問題を解決している小さな取得する必要があります。 2番目の重要なアイデアは、各ステップが同じであるということです。
この場合、ピースを配置し、配置されたピースを取り外した状態で再びボード上で関数を呼び出すことがあります。もう少し詳しく教えてください。
- ピースを配置して機能を呼び出すたびに、ピースを配置できる位置の数を減らします。
- この関数をもう一度呼び出すたびに、タイルを配置しようとしています。したがって、問題のスペースは小さくても問題は一貫しています。
希望します。
関連する問題
- 1. 再帰的なXQuery関数で一致する要素を数える方法
- 2. Linuxの再帰的一括編集
- 3. 二乗ベクトル要素を再帰的に
- 4. XmlSchemaDocumentの要素部分の再帰的検索
- 5. 文字列要素のリストを再帰的に連結する方法
- 6. ベクトル要素の再帰的操作
- 7. 再帰的クエリを動的に作成する方法は?
- 8. バイナリツリーに再帰的に挿入する方法と再帰的に要素を印刷する方法はありますか?
- 9. Scala:再帰的に要素/リストのリストを変更する
- 10. Racket:リスト内の要素を再帰的に比較する
- 11. lxmlのspeceific要素とサブ要素を再帰的に取得する方法は?
- 12. 要素をBinaryTreeに再帰的に挿入する
- 13. Scalaでこの再帰的メソッドの尾を再帰的にする方法は?
- 14. XSDで再帰的な要素構造を指定する方法は?
- 15. QlikView:リストボックス内の要素の再編成を無効にする
- 16. Vuejs2 - "tr"要素を再帰的に反復する
- 17. Scala再帰的に要素数を指定する述語
- 18. XSLTの要素を再帰的に置き換える
- 19. CSSですべての子要素を再帰的に選択
- 20. リスト内の要素を再帰的メソッドでカウントする
- 21. 再帰的フェッチ要求を作成する方法はありますか?
- 22. MySQLで一番上の再帰を再帰的に選択
- 23. スレッド再帰的な方法
- 24. 再帰的な方法
- 25. 再帰的にディレクトリを作成する
- 26. 要素の下にあるすべての子を再帰的に選択する方法Javascript
- 27. 2D配列内の要素の位置を返す再帰的
- 28. 素数再帰的なStackOverflowException
- 29. 再帰的なdeftypeを達成する方法
- 30. Bash:再帰的にサブディレクトリを再作成
@fragilewindows、私もあなたの改善と、それがスタックオーバーフローの基準を満たしていないので、この質問へのあなたの提案編集を拒否するように投票しています。この質問は、サイトのリソースを犠牲にすることを求めており、閉鎖する必要があります。 – HPierce