// http://u...content-available-to-author-only...e.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=691
// Kaushik Acharya
#include <iostream>
#include <fstream>
#include <vector>
#include <cassert>
const bool READ_FROM_FILE = false;
//We are considering a column for each queen
template<typename T>
class Queen
{
public:
Queen()
: relValidPos_(0)
{
}
public:
T currentPos()
{
assert((relValidPos_ < vecValidPos_.size()) && "can't provide a valid position");
return vecValidPos_[relValidPos_];
}
void addValidPos(T pos)
{
vecValidPos_.push_back(pos);
}
void moveToNextPos()
{
//Note: If this queen is currently at last valid position, then this call will move it to an invalid position.
//So its necessary to check the validity of this queen's position before using it.
++relValidPos_;
}
bool isCurrentPosValid()
{
return (relValidPos_ < vecValidPos_.size());
}
void clearAllPos()
{
//This is called when we want to backtrack to a queen at higher level.
vecValidPos_.clear();
relValidPos_ = 0;
}
bool empty()
{
return vecValidPos_.empty();
}
private:
std::vector<T> vecValidPos_; //This stores all valid positions for the queen in current state of the game
T relValidPos_; //This indicates the relative index of the queen in the valid positions in vecValidPos_
};
template<typename T>
class Chess
{
public:
Chess(T size=8)
: size_(size)
{
vecOrderQueen.reserve(size_);
vecQueen_.reserve(size_);
for (T q_i = 0; q_i != size_; ++q_i)
{
Queen<T> queen;
vecQueen_.push_back(queen);
}
/*
vecQueenPosVec_.reserve(size_);
vecQueenRelPos_.reserve(size_);
for (T q_i = 0; q_i != size_; ++q_i)
{
vecQueenPosVec_.push_back(std::vector<T>());
vecQueenRelPos_.push_back(size_); //initialize with invalid relative position
}
*/
}
public:
void assign_initial_queen(T row, T col)
{
vecOrderQueen.push_back(col);
//now assign the rest of the queens
for (T q_i = 0; q_i != size_; ++q_i)
{
if (q_i != col)
{
vecOrderQueen.push_back(q_i);
}
else
{
vecQueen_[q_i].addValidPos(row);
/*
vecQueenPosVec_[q_i].push_back(col);
vecQueenRelPos_[q_i] = 0;
*/
}
}
}
void compute_arrangements();
void print_header();
void print_arrangements();
private:
void populate_valid_positions_for_next_queen(T queen_index_in_queen_list);
private:
T size_; //chess square is size_*size_
std::vector<Queen<T> > vecQueen_;
std::vector<std::vector<T> > vecArrangement_;
// Next one stores queen in a different order than above.
std::vector<T> vecOrderQueen; //First one is the initial queen. Rest of the queens are traversed sequentially in backtracking
};
template<typename T>
void Chess<T>::compute_arrangements()
{
T relPos = 0;
while (true)
{
T queen_index = vecOrderQueen[relPos];
bool flag_backtrack = false;
if (vecQueen_[queen_index].isCurrentPosValid())
{
if (relPos == (size_-1))
{
// current level is the last level in the hierarchy
// collect this arrangement
std::vector<T> arrangement;
arrangement.reserve(size_);
for (typename std::vector<Queen<T> >::iterator it = vecQueen_.begin(); it != vecQueen_.end(); ++it)
{
arrangement.push_back((*it).currentPos());
}
vecArrangement_.push_back(arrangement);
vecQueen_[queen_index].moveToNextPos();
}
else
{
populate_valid_positions_for_next_queen(++relPos);
}
}
else
{
// backtrack to higher level
flag_backtrack = true;
}
if (flag_backtrack)
{
vecQueen_[queen_index].clearAllPos();
if (relPos == 0)
{
break;
}
--relPos;
T prev_queen_index = vecOrderQueen[relPos];
vecQueen_[prev_queen_index].moveToNextPos();
}
}
}
template<typename T>
void Chess<T>::print_header()
{
std::cout << "SOLN COLUMN" << std::endl;
std::cout << " # ";
for (T q_i = 0; q_i != size_; ++q_i)
{
std::cout << " " << (q_i+1);
}
std::cout << std::endl;
}
template<typename T>
void Chess<T>::print_arrangements()
{
std::cout << std::endl;
for (T arrangement_i = 0; arrangement_i != vecArrangement_.size(); ++arrangement_i)
{
std::cout << " " << (arrangement_i+1) << " ";
for (T q_i = 0; q_i != size_; ++q_i)
{
std::cout << " " << vecArrangement_[arrangement_i][q_i]+1;
}
std::cout << std::endl;
}
}
template<typename T>
void Chess<T>::populate_valid_positions_for_next_queen(T queen_index_in_queen_list)
{
T queen_index = vecOrderQueen[queen_index_in_queen_list];
assert(vecQueen_[queen_index].empty() && "valid position list for the current queen row is expected to be empty");
// we will check validity for each row in the column belonging to this queen
for (T pos = 0; pos != size_; ++pos)
{
bool valid_pos_flag = true;
// check one by one the queens at higher level
for (T q_i = 0; q_i != queen_index_in_queen_list; ++q_i)
{
T other_queen_index = vecOrderQueen[q_i];
T other_queen_pos = vecQueen_[other_queen_index].currentPos();
if (pos == other_queen_pos)
{
valid_pos_flag = false;
break;
}
T diff_in_col = 0;
if (other_queen_index < queen_index)
{
diff_in_col = queen_index - other_queen_index;
}
else
{
diff_in_col = other_queen_index - queen_index;
}
T diff_in_row = 0;
if (pos < other_queen_pos)
{
diff_in_row = other_queen_pos - pos;
}
else
{
diff_in_row = pos - other_queen_pos;
}
if (diff_in_row == diff_in_col)
{
valid_pos_flag = false;
break;
}
}
if (valid_pos_flag)
{
vecQueen_[queen_index].addValidPos(pos);
}
}
}
int main(int argc, char* argv[])
{
unsigned int nDataSet;
std::ifstream pFile;
if (READ_FROM_FILE)
{
pFile.open("D:/cpp_practise/online_judge/uva/750_8_Queens_Chess_Problem_input.txt",std::ios::in);
assert(pFile.is_open() && "input file not opened");
}
if (READ_FROM_FILE)
{
pFile >> nDataSet;
}
else
{
std::cin >> nDataSet;
}
for (unsigned int dataset_i = 0; dataset_i != nDataSet; ++dataset_i)
{
Chess<unsigned int> chess(8);
unsigned int initial_queen_row, initial_queen_col;
if (READ_FROM_FILE)
{
pFile >> initial_queen_row >> initial_queen_col;
}
else
{
std::cin >> initial_queen_row >> initial_queen_col;
}
// convert to zero-indexed
--initial_queen_row;
--initial_queen_col;
chess.assign_initial_queen(initial_queen_row,initial_queen_col);
chess.compute_arrangements();
if (dataset_i > 0)
{
std::cout << std::endl;
}
chess.print_header();
chess.print_arrangements();
}
if (READ_FROM_FILE)
{
pFile.close();
}
return 0;
}
/*
Test cases:
http://o...content-available-to-author-only...a.es/board/viewtopic.php?p=27847#p27847
http://o...content-available-to-author-only...a.es/board/viewtopic.php?p=39105#p39105
*/