1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
#include <iostream>
#include <string>
#include <set>
#include <queue>
#include <map>
#include <algorithm>
using namespace std;
//--------------------------------------
struct node
{
string str;
int step;
};
//--------------------------------------
void drawBoard( const string &str )
{
for ( int row = 0; row < 3; row++ ) cout << str.substr( 3 * row, 3 ) << '\n';
}
//--------------------------------------
void traceRoute( map<string,string> &M, string s )
{
cout << "Route traced (backwards):\n\n";
for ( ; s != ""; s = M[s] ) { drawBoard( s ); cout << '\n'; }
}
//--------------------------------------
void bfs( const string &start, const string &target )
{
// Input validation
if ( start .size() != 9
|| target.size() != 9
|| start .find_first_not_of( "012345678" ) != string::npos
|| target.find_first_not_of( "012345678" ) != string::npos )
{
cout << "Invalid input\n";
return;
}
else if ( start == target )
{
cout << "Start == target\n";
drawBoard( target ); cout << '\n';
return;
}
// Main solver
int jump[] = { -1, 1, -3, 3 }; // left, right, up, down
queue<node> Q; // current search front
set<string> S; // set of configurations that have been reached
map<string,string> M; // sequence of predecessors for tracing route
Q.push( { start, 0 } );
S.insert( start );
M[start] = "";
while( !Q.empty() )
{
// Take next element from FIFO queue and check every configuration accessible from it
node p = Q.front(); Q.pop();
int pos = p.str.find( '0' ); // position of blank space in the board
for ( int jp : jump )
{
string str = p.str;
int sop = pos + jp; // position of tile that could be slid into blank space
if ( sop < 0 || sop >= 9 || ( pos % 3 == 0 && jp == -1 ) || ( pos % 3 == 2 && jp == +1 ) ) continue;
// outside board (top, bottom, left, right), so ignore
swap( str[pos], str[sop] ); // slide tile across
if ( str == target ) // check for completion
{
M[str] = p.str;
traceRoute( M, str ); // trace back the route to the solution
cout << "Solved in " << p.step + 1 << " steps\n";
return;
}
if ( S.insert( str ).second ) // if not already met, add to new front
{
Q.push( { str, p.step + 1 } ); // add new element to front, distance one step further
M[str] = p.str;
}
}
}
cout << "Can't be solved\n";
}
//--------------------------------------
int main()
{
bfs( "134825760", "123804765" );
}
|