根据用户输入的电路板尺寸编号,我有一些用于在控制台中显示n-queens问题的代码。
以下是代码:
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
class point
{
public:
int x, y;
point() { x = y = 0; }
void set( int a, int b ) { x = a; y = b; }
};
class nQueens
{
public:
void solve( int c )
{
_count = c;
int len = (c + 1) * (c + 1);
_queens = new bool[len]; memset( _queens, 0, len );
_cl = new bool[c]; memset( _cl, 0, c );
_ln = new bool[c]; memset( _ln, 0, c );
point pt; pt.set( rand() % c, rand() % c );
putQueens( pt, c );
displayBoard();
delete [] _queens; delete [] _ln; delete [] _cl;
}
private:
void displayBoard()
{
system( "cls" );
const string t = "+---+", q = "| Q |", s = "| |";
COORD c = { 0, 0 };
HANDLE h = GetStdHandle( STD_OUTPUT_HANDLE );
for (int y = 0, cy = 0; y < _count; ++y)
{
int yy = y * _count;
for ( int x = 0; x < _count; x++ )
{
SetConsoleCursorPosition( h, c ); cout << t;
c.Y++; SetConsoleCursorPosition( h, c );
if (_queens[x + yy]) cout << q; else cout << s;
c.Y++; SetConsoleCursorPosition( h, c );
cout << t; c.Y = cy; c.X += 4;
}
cy += 2; c.X = 0; c.Y = cy;
}
}
bool checkD( int x, int y, int a, int b )
{
if ( x < 0 || y < 0 || x >= _count || y >= _count ) return true;
if ( _queens[x + y * _count] ) return false;
if ( checkD( x + a, y + b, a, b ) ) return true;
return false;
}
bool check( int x, int y )
{
if ( _ln[y] || _cl[x] ) return false;
if ( !checkD( x, y, -1, -1 ) ) return false;
if ( !checkD( x, y, 1, -1 ) ) return false;
if ( !checkD( x, y, -1, 1 ) ) return false;
if ( !checkD( x, y, 1, 1 ) ) return false;
return true;
}
bool putQueens( point pt, int cnt )
{
int it = _count;
while (it)
{
if ( !cnt ) return true;
if ( check( pt.x, pt.y ) )
{
_queens[pt.x + pt.y * _count] = _cl[pt.x] = _ln[pt.y] = true;
point tmp = pt;
if ( ++tmp.x >= _count ) tmp.x = 0;
if ( ++tmp.y >= _count ) tmp.y = 0;
if ( putQueens( tmp, cnt - 1 ) ) return true;
_queens[pt.x + pt.y * _count] = _cl[pt.x] = _ln[pt.y] = false;
}
if ( ++pt.x >= _count ) pt.x = 0;
it--;
}
return false;
}
int _count;
bool* _queens, *_ln, *_cl;
};
int main( int argc, char* argv[] )
{
nQueens n; int nq;
while( true )
{
system( "cls" );
cout << "Enter board size bigger than 3 (0 - 3 to QUIT): "; cin >> nq;
if ( nq < 4 ) return 0;
n.solve( nq ); cout << endl << endl;
system( "pause" );
}
return 0;
}
控制台显示是这样的。假设我输入4:
然后结果:
我想知道我是否可以在应用程序中添加另一种可能性,因为4x4板可以有2个解决方案。一些帮助将不胜感激 - 谢谢!
ps:代码不是由我完全创建的,我完全忘记了我是如何获得第一个代码算法的,我对此代码不予理睬:)
答案 0 :(得分:1)
我认为你的算法只生成一个答案。 你应该以某种方式组织它,当下一个答案可以从电路板的存储状态计算出来。皇后。
NQueens q;
while(q.next()) // search next solution
{
q.clearScreen(); // OR clrscr();
q.displayBoard();
char c = getch();
if(c != ' ') break; // Interrupt loop when user press key, but not space
// When user press space he will see next answer
}
答案 1 :(得分:1)
#include <iostream>
using namespace std;
const int N = 5;
int position[N];
// Check if a position is safe
bool isSafe(int queen_number, int row_position)
{
// Check each queen before this one
for(int i=0; i<queen_number; i++)
{
// Get another queen's row_position
int other_row_pos = position[i];
// Now check if they're in the same row or diagonals
if(other_row_pos == row_position || // Same row
other_row_pos == row_position - (queen_number-i) || // Same diagonal
other_row_pos == row_position + (queen_number-i)) // Same diagonal
return false;
}
return true;
}
// Recursively generate a tuple like [0 0 0 0], then [0 0 0 1] then etc...
void solve(int k)
{
if(k == N) // We placed N-1 queens (0 included), problem solved!
{
// Solution found!
cout << "Solution: ";
for(int i=0; i<N; i++)
cout << position[i] << " ";
cout << endl;
}
else
{
for(int i=0; i<N; i++) // Generate ALL combinations
{
// Before putting a queen (the k-th queen) into a row, test it for safeness
if(isSafe(k,i))
{
position[k] = i;
// Place another queen
solve(k+1);
}
}
}
}
int main()
{
solve(0);
return 0;
}
希望这会有所帮助:)
答案 2 :(得分:0)
而不是return true
:
if( !cnt )
return true;
让它显示结果(即调用displayBoard
),然后返回false
。这将导致求解器继续运行,直到它耗尽所有可能性。
您需要移除displayBoard
中solve
的来电,并且您可能需要调整您正在调用的地点system("CLS")
,以便获得您喜欢的整体结果。
答案 3 :(得分:0)
if( !cnt )
return true;
让它显示结果(即调用displayBoard
),然后显示return false
。这将导致求解器继续运行,直到它耗尽所有可能性。
您需要在解决时删除对displayBoard
的调用,并且您可能需要调整您正在调用系统的位置(“CLS
”)以获得您喜欢的整体结果