Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#11 Branch and Bound (BFS traversing) #17

Merged
merged 11 commits into from
Jun 1, 2023
141 changes: 141 additions & 0 deletions C++/Algorithms/8-puzzle problem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
//
// Created by 김지민 on 2023/05/22.
//

/*
* 8-puzzle problem
* given a 3X3 board with 8 tiles (every tile has one number from 1 to 8 ) and one empty space.
* The objective is to place the numbers on tiles to match the final configuration using the empty space.
* We can slide four adjacent (left, right, above and below) tiles into the empty space.
*
* 1. Design:
* Design Approach: Branch and Bound(BFS)
* Step 1. designing promising function
* C(X) = g(X) + h(X)
* g(X): cost of reaching the current node from the root
* h(X): cost of reaching an answer node from X
* Step 2. BFS traverse, visit
*/

/*
* 2. Implementation
*/
#include <iostream>
#include <queue>
using namespace std;
#define N 3

struct Node {
Node* parent;
int mat[N][N];
int x, y; // coordinate of blank tile
int cost; // # of misplaced tiles
int level; // # of moves so far
};

int printMatrix(int mat[N][N]) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%d ", mat[i][j]);
}
printf("\n");
}
}

// allocating new node
Node* newNode(int mat[N][N], int x, int y, int newX, int newY, int level, Node* parent) {
Node* node = new Node;
node->parent = parent;
memcpy(node->mat, mat, sizeof node->mat);
swap(node->mat[x][y], node->mat[newX][newY]);
node->cost = INT_MAX;
node->level = level;
node->x = newX;
node->y = newY;

return node;
}

int row[] = {1, 0, -1, 0};
int col[] = {0, -1, 0, 1};

// calculating # of misplaced tiles
int calculateCost(int initial[N][N], int final[N][N]) {
int count = 0;
for (int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {

// counting the number of mis-placed tiles
if (initial[i][j] && initial[i][j] != final[i][j]) {
count++;
}
}
}
return count;
}

// check if (x, y) is a valid matrix coordinate
int isSafe(int x, int y) {
return (x >= 0 && x < N && y >= 0 && y < N);
}

void printPath(Node* root) {
if (root == NULL) {
return;
}
printPath(root->parent);
printMatrix(root->mat);

printf("\n");
}

struct comp {
bool operator() (const Node* lhs, const Node* rhs) const {

// the smaller g(X) + h(X) is, the higher it is placed.
return (lhs->cost + lhs->level) > (rhs->cost + rhs->level);
}
};

void solve(int initial[N][N], int x, int y, int final[N][N]) {
priority_queue<Node*, std::vector<Node*>, comp> pq;
Node* root = newNode(initial, x, y, x, y, 0, NULL);
root-> cost = calculateCost(initial, final); // calculating h(X)

pq.push(root);

while (!pq.empty()) {
Node* min = pq.top(); // finding a live node with the least estimated cost
pq.pop();

// min is the answer node
if (min->cost == 0) {
printPath(min);
return;
}

for (int i = 0; i < 4; i++) {
if (isSafe(min->x + row[i], min->y + col[i])) {
Node* child = newNode(min->mat, min->x, min->y,
min->x + row[i], min->y + col[i],
min->level + 1, min);
child->cost = calculateCost(child->mat, final);
pq.push(child);
}
}
}
}

int main() {
int initial[N][N] = {{1, 2, 3},
{5, 6, 0},
{7, 8, 4}};
int final[N][N] = {{1, 2, 3},
{5, 8, 6},
{0, 7, 4}};
int x = 1, y = 2;

solve(initial, x, y, final);

return 0;
}
90 changes: 90 additions & 0 deletions C++/Algorithms/N-Queens problem Backtracking 2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//
// Created by 김지민 on 2023/05/22.
//

/*
* N-Queens Problem
* the problem of placing N chess queens of an NxN chessboard so that no two queens attack each other.
*
* 1. Design:
* Design Approach: Backtracking(DFS)
* Step 1. designing promising function
* Step 2. DFS traverse, visit
*/

/*
* 2. Implementation
*/
#include <iostream>
#include <vector>
using namespace std;
int N;

// printing the solution
void printSol(vector<vector<int> >board) {
for (int i = 0; i<N; i++) {
for (int j = 0; j<N; j++) {
cout << board[i][j] << " ";
}
cout << "\n";
}
}

// checking if current row, left diagonal, right diagonal contain any queen
bool isSafe(int row, int col, vector<bool> rows, vector<bool> left_diagonals, vector<bool> right_diagonals) {
if (rows[row] || left_diagonals[row + col] || right_diagonals[col - row + N - 1]) {
return false;
}
return true;
}

// recursive function for N-queens problem
bool solve(vector<vector<int> >& board, int col, vector<bool> rows, vector<bool> left_diagonals, vector<bool> right_diagonals) {

// all queens are placed
if (col >= N) {
return true;
}

// move in all rows one by one
for (int i = 0; i < N; i++) {
if (isSafe(i, col, rows, left_diagonals, right_diagonals)) { // placing a queen
rows[i] = true;
left_diagonals[i + col] = true;
right_diagonals[col - i + N - 1] = true;
board[i][col] = 1;

// recurrence
if (solve(board, col + 1, rows, left_diagonals, right_diagonals)) {
return true;
}

// backtracking
rows[i] = false;
left_diagonals[i + col] = false;
right_diagonals[col - i + N - 1] = false;
board[i][col] = 0;
}
}
return false;
}

int main() {
cout << "Enter the no of rows for the square Board : ";
cin >> N;

vector<vector<int> > board(N,vector<int>(N,0));

vector<bool> rows(N,false);

vector<bool> left_diagonals(2*N-1,false);
vector<bool> right_diagonals(2*N-1,false);

bool ans = solve(board, 0, rows, left_diagonals, right_diagonals);

if (ans) {
printSol(board);
} else {
cout<<"Solution Does not Exist\n";
}
}
92 changes: 92 additions & 0 deletions C++/Algorithms/N-Queens problem Branch and Bound.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//
// Created by 김지민 on 2023/06/01.
//

/*
* N-Queens Problem
* the problem of placing N chess queens of an NxN chessboard so that no two queens attack each other.
*
* 1. Design:
* Design Approach: Branch and Bound(BFS)
* Step 1. designing promising function
* Step 2. BFS traverse, visit
*/

/*
* 2. Implementation
*/
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

struct State {
vector<int> queens;
int row;
};

bool isSafe(const vector<int>& queens, int row, int col) {
for (int i = 0; i < row; i++) {
if (queens[i] == col || queens[i] - col == i - row || queens[i] - col == row - i) {
return false;
}
}
return true;
}

vector<int> solveNQueens(int n) {
vector<int> queens(n, -1); // to store column positions of queens
// queens[row] : the column position of the queen in the row-th row
queue<State> states; // to store the states to be explored

State initial_state;
initial_state.row = 0;
states.push(initial_state);

while (!states.empty()) {
State current_state = states.front();
states.pop();

int current_row = current_state.row;
if (current_row == n) { // all queens have been placed
queens = current_state.queens;
break;
} else {
for (int col = 0; col < n; col++) {
if (isSafe(current_state.queens, current_row, col)) {
State new_state = current_state;
new_state.queens.push_back(col);
new_state.row++;

states.push(new_state);
}
}
}
}

return queens;
}

void printSolution(const vector<int>& queens) {
int n = queens.size();
if (queens.empty()) {
cout << "No solution found.";
} else {
cout << "Found a solution:\n";
for (int row = 0; row < n; row++) {
for (int col = 0; col < n; col++) {
cout << (queens[row] == col ? "Q " : ". ");
}
cout << "\n";
}
}
}

int main() {
int n = 4; // Board size

vector<int> solution = solveNQueens(n);
printSolution(solution);

return 0;
}
Loading