最初のエラーは、ローカル変数を使用する必要がある再帰関数でメンバー変数を使用することです。ここには2つの変種があります:各呼び出しから数値を返すか、グローバル関数またはメンバ関数を持ち、そこで解を累積します。これらのアプローチを混在させないでください。
オリジナルのポストではありませんでした2番目のエラー、がありますが、全体のコードを掲示したときに導入された、ここにある:
// try placing piece in row of col
for (int i = 0; i < boardSize; i++){
board[col][i] = 1;
if (canPlace(col, i, board)) {
nsolutions += findNumSolutions(board, col + 1, rooksLeft - 1);
board[col][i] = 0;
}
}
:
// try placing piece in row of col
for(int i = 0; i < boardSize; i++){
board[col][i] = 1;
if(!canPlace(col, i, board)){
continue;
}
nsolutions += findNumSolutions(board, col + 1, rooksLeft - 1);
board[col][i] = 0;
}
これは同等です
ルークの設定と復元は対称でなければなりません。ルーキーが置かれるたびに、新しいルーキーを置こうとする前に、または再びルーキーをやり直す前に、それを休まなければなりません。ルークはすべての場合に配置されているが、配置できるときにのみクリーンアップされていることがわかります。この結果、より多くのルークがボード上にある必要があります。
このチェックでは現在の列は考慮されないため、両方のルックプレースメントを中かっこの外側に配置することができます。私は次のように提案します:
for (int i = 0; i < boardSize; i++){
if (canPlace(col, i, board)) {
board[col][i] = 1;
nsolutions += findNumSolutions(board, col + 1, rooksLeft - 1);
board[col][i] = 0;
}
}
補足として、私はそのクラスが自分のボードを管理すべきだと思います。これは多くの混乱を避けるでしょうboard
パラメータ。ヒープにボードサイズを割り当てる場合は、MAXSIZE
も必要ありません。しかし、注意:ボードのサイズが大きくなると、アレンジの数はint
をオーバーフローします。
#include <iostream>
class NRooks {
public:
NRooks(int n, int k);
~NRooks();
int getSolutionTotal();
private:
bool canPlace(int col, int row);
int findNumSolutions(int col, int rooksLeft);
int numSolutions;
int numRooks;
int boardSize;
int *data;
int **board;
};
NRooks::NRooks(int n, int k)
{
numRooks = n;
boardSize = k;
numSolutions = 0;
data = new int[k*k];
board = new int*[k];
for (int i = 0; i < k; i++) board[i] = data + k*i;
for (int i = 0; i < k*k; i++) data[i] = 0;
numSolutions = findNumSolutions(0, numRooks);
}
NRooks::~NRooks()
{
delete[] data;
delete[] board;
}
int NRooks::getSolutionTotal(){
return numSolutions;
}
bool NRooks::canPlace(int col, int row)
{
for (int i = col; i-- > 0;) {
if (board[i][row]) return false;
}
return true;
}
int NRooks::findNumSolutions(int col, int rooksLeft)
{
if (rooksLeft == 0) return 1;
if (col > boardSize) return (rooksLeft == 0);
int nsolutions = 0;
for (int i = 0; i < boardSize; i++) {
if (canPlace(col, i)) {
board[col][i] = 1;
nsolutions += findNumSolutions(col + 1, rooksLeft - 1);
board[col][i] = 0;
}
}
if (rooksLeft < boardSize - col) {
nsolutions += findNumSolutions(col + 1, rooksLeft);
}
return nsolutions;
}
int main()
{
for (int boardSize = 2; boardSize <= 6; boardSize++) {
for (int numPieces = 1; numPieces <= boardSize; numPieces++) {
NRooks r = NRooks(numPieces, boardSize);
std::cout << boardSize << " board, "
<< numPieces << " rooks, "
<< r.getSolutionTotal() << " solutions"
<< std::endl;
}
}
return 0;
}
で説明した手法を使用しています 'グローバル変数や'NRooks'のメンバーをnumSolutions'ていますか? 'findNumSolutions'の各呼び出しはそれ自身のコピーを必要とするため、ローカルにします。 –
それは私が逃した一つのことです。しかし、まだ "0"です。うん、私は何を得ているのか知っている私はなぜこれが動作していないのだろうかと思っている – wanderbread
メンバー変数の変更を変更するだけです。 'numSolutions = 0;'を、 'NRooks :: findNumSolutions'にローカル変数の宣言に追加します:' int numSolutions = 0; '。 (そして同じ名前のメンバ変数を削除します;あなたはそれを必要としません)。今すぐ動作するはずです。 –