Branch and Bound Algorithm for solving Assignment-probleem - c++

I started doing Branch and Bound Algorithm for assignment problem in C++ and i can't find the right solution. First of all assignment problem example:
Assignment problem
Ok so each person can be assigned to one job, and the idea is to assign each job to one of the person so that all the jobs are done in the quickest way.
Here is my code so far:
#include "Matrix.h"
// Program to solve Job Assignment problem
// using Branch and Bound
#include <limits.h>
#include <vector>
#include <algorithm>
using namespace std;
template<class T>
NUM getCost(Matrix& matrix, size_t x, size_t y, vector<bool>& colUsed);
void run(Matrix& matrix, vector<size_t>& assignedJobs);
int main()
{
Matrix matrix;
matrix.setMatrix(N);
matrix.print();
vector<size_t> assignedJobs;
run(matrix, assignedJobs);
cout << assignedJobs[0];
/*
cout << "size:E " << v.size() << endl;
for (vector<NUM>::iterator i = v.begin(); i != v.end(); i++)
{
cout << *i << endl;
}
*/
return 0;
}
// remember to use x only LOCALLY!!!
NUM getCost(Matrix& matrix, size_t x, size_t y, vector<bool>& colUsed)
{
// pathCost
NUM pathCost = matrix.matrix[x++][y];
for (size_t col = 0; col < matrix.size(); col++)
{
if (!colUsed.at(col))
{
NUM min =
#if defined NUM_INT
INT_MAX;
#endif
#if defined NUM_DBL
DBL_MAX;
#endif
size_t row = x;
for (; row < matrix.size(); row++)
{
if (min > matrix.matrix[row][col])
{
min = matrix.matrix[row][col];
}
}
pathCost += min;
}
}
return pathCost;
}
void run(Matrix& matrix, vector<size_t>& assignedJobs)
{
// array of used columns
vector<bool> colUsed;
for (size_t i = 0; i < matrix.size(); i++)
{
colUsed.push_back(false);
}
for (size_t row = 0; row < matrix.size(); row++)
{
size_t col = 0;
// bombona
while (colUsed.at(col++)); col--;
// choose the best job for the current worker
vector<NUM> jobs;
// get all the job costs from which to choose the smallest
// row++
jobs.push_back(getCost(matrix, col, row, colUsed));
// iterator at the position of the smallest element of jobs
vector<NUM>::iterator i_min = min_element(jobs.begin(), jobs.end());
// index of the smallest element in jobs
size_t index = (size_t)distance(jobs.begin(), i_min);
colUsed.at(index) = true;
assignedJobs.push_back(index);
}
}
I know i might be out of track. I didn't use lower bound in the beginning, i'm actually a little confused how this algorithm exactly works. So even step by step walktrough through the algorithm would be helpful.

Related

Given an N by M matrix consisting only of 1's and 0's, find the largest rectangle containing only 1's and return its area

This was an interview question and I have written the answer, but it's not working. Can anyone please suggest an optimized answer or point out my mistake.
#include<bits/stdc++.h>
using namespace std;
void printMaxArea(bool M[R][C]){
int i,j;
int S[R][C];
int maxs,maxi,maxj;
int area=0;
//set 1st column
for(i=0;i<R;i++)
S[i][0]=M[i][0];
//set 1st row
for(j=0;j<C;j++)
S[0][j]=M[0][j];
//other entries
for(i=1;i<R;i++){
for(j=1;j<C;j++){
if(M[i][j]==1)
S[i][j]=min(S[i][j-1],min(S[i-1][j],S[i-1][j-1])+1);
else
S[i][j]=0;
}
}
//maximum entry and index
maxs=S[0][0];
maxi=0;
maxj=0;
for(i=0;i<R;i++){
for(j=0;j<C;j++){
if(maxs<S[i][j]){
maxs=S[i][j];
maxi=i;
maxj=j;
}
}
}
for(i=maxi;i>maxs-maxi;i--){
for(j=maxj;j>maxs-maxj;j--){
area=area+M[i][j];
}
}
cout<<area;
}
int main(){
int M[R][C]={{1,0,0,0},
{1,0,1,1},
{1,0,1,1},
{0,1,0,0}};
printMaxArea(M);
}
Any help will be appreciated.
So, we are here to help. Let me list up the flaws in this post
I am not sure, if this was an interview question
The base answer was given by user rathbhupendra on GeeksForGeeks. See here
Your posted code is a nearly one to one copy from the above linked post from GeeksForGeeks
Your question text does not match. You are talking about rectangular. The code will work only for square sub-metrices
Where you did not exactly copy and paste, you created the errors. There are 2:
The correct line should be:
S[i][j] = min(S[i][j-1],min( S[i-1][j], S[i-1][j-1])) + 1;
See the +1 at then end. You put it in brackets.
The second error is in the last for llop, where you calculate the sum. You made a copy and past error in the loop condition. The correct code is
for(i = max_i; i > max_i - max_of_s; i--)
{
for(j = max_j; j > max_j - max_of_s; j--)
You mixed maxi and maxs.
Let me additionally explain that the C++ code on GeeksForGeeks is mostly horrible. Very often the C++ page is a one to one copy from C. Maybe adding on C++ statement like std::cout. But has nothing to do with C++
The presented code for this solution is extraordinary bad C++ code and should not be used, under no circumstance.
With only minor effort, you could convert the bad code in somewhat readable.
PPlease have a look here:
#include <iostream>
#include <algorithm>
constexpr size_t NumberOfRows = 4U;
constexpr size_t NumberOfColumns = 4U;
void printMaxArea(int (&matrix)[NumberOfRows][NumberOfColumns]) {
int subMatrixSums[NumberOfRows][NumberOfColumns] = {};
//set 1st column
for (size_t row = 0U; row < NumberOfRows; ++row)
subMatrixSums[row][0U] = matrix[row][0U];
//set 1st row
for (size_t col = 0U; col < NumberOfColumns; ++col)
subMatrixSums[0U][col] = matrix[0][col];
//other entries
for (size_t row = 1U; row < NumberOfRows; ++row) {
for (size_t col = 1U; col < NumberOfColumns; ++col) {
if (matrix[row][col] == 1) {
subMatrixSums[row][col] = std::min(subMatrixSums[row][col - 1U], std::min(subMatrixSums[row - 1U][col], subMatrixSums[row - 1U][col - 1U])) + 1;
}
}
}
//maximum entry and index
int maxSubMatrixSums{ subMatrixSums[0U][0U] };
int maxRow{};
int maxCol{};
for (size_t row = 0U; row < NumberOfRows; ++row) {
for (size_t col = 0U; col < NumberOfColumns; ++col) {
if (maxSubMatrixSums < subMatrixSums[row][col]) {
maxSubMatrixSums = subMatrixSums[row][col];
maxRow = row;
maxCol = col;
}
}
}
int area{};
for (int row = maxRow; row > maxRow- maxSubMatrixSums; --row) {
for (int col = maxCol; col > maxCol- maxSubMatrixSums; col--) {
area = area + matrix[row][col];
}
}
std::cout << area;
}
int main() {
int matrix[NumberOfRows][NumberOfColumns] = {
{1,0,0,0},
{1,0,1,1},
{1,0,1,1},
{0,1,0,0} };
printMaxArea(matrix);
return 0;
}
Of course there is also a C++ solution:
#include <iostream>
#include <algorithm>
#include <array>
// This function calculates the number of elements, the size, of the biggest square sub matrix.
// It uses a sub matrix for calculating the sums of submatrices
// The algorithm looks at the left, upper, upper-left element and adds 1 to minimum sum of the 3
// As a result, the lower right corner of such a square submatrics will contain the biggest sum
constexpr size_t NumberOfRows = 4U;
constexpr size_t NumberOfColumns = 4U;
constexpr size_t NumberOfElements = NumberOfRows * NumberOfColumns;
using MyType = int;
using Row = std::array<MyType, NumberOfColumns>;
using Matrix = std::array<Row, NumberOfRows>;
void printSizeMaxSquareSubArea(Matrix &matrix) {
// Using the sub matrix as a one dimensional array
std::array<MyType, NumberOfElements> subMatrixSums{};
// Copy first row
std::copy(matrix[0].begin(), matrix[0].end(), subMatrixSums.begin());
// Copy first column
for (size_t row = 0U; row < NumberOfRows; ++row)
subMatrixSums[row*NumberOfColumns] = matrix[row][0U];
// Calculate sums
for (size_t row = 1U; row < NumberOfRows; ++row) {
for (size_t col = 1U; col < NumberOfColumns; ++col) {
if (matrix[row][col] == 1) {
subMatrixSums[row * NumberOfColumns + col] =
std::min(subMatrixSums[row * NumberOfColumns + col - 1U],
std::min(subMatrixSums[(row - 1U) *NumberOfColumns + col],
subMatrixSums[(row - 1U) * NumberOfColumns + col - 1])) + 1;
}
}
}
// Get max value
const int maxSubMatrixSums = *std::max_element(subMatrixSums.begin(), subMatrixSums.end());
// Show result
std::cout << "Size: " << maxSubMatrixSums * maxSubMatrixSums << '\n';
}
// Driver code
int main()
{
Matrix M{ {
{1,0,0,0},
{1,0,1,1},
{1,0,1,1},
{0,1,0,0}
} };
printSizeMaxSquareSubArea(M);
}

Pascal's Triangle by recursive function

int Pascal_Tri(int row , int col)
{
if (row==col || col==0)
return 1 ;
else
{
return Pascal_Tri(row-1,col)+Pascal_Tri(row-1,col-1);
}
}
there is a problem with this code and I can not discover it.
when I run it, the program stops working and no results disappear
C++11
#include <iostream>
#include <vector>
std::vector<int> pascal(int height, std::vector<int> curr)
{
for(int i=0; i<curr.size(); i++)
std::cout<<curr[i]<<" ";
std::cout<<std::endl;
if(height<=0)
return curr;
std::vector<int> newCurr(curr.size()+1,1);
for(int i=0; i+1 < curr.size(); i++)
newCurr[i+1] = curr[i] + curr[i+1];
return pascal(height-1,newCurr);
}
int main()
{
int row, col;
std::cin>>row>>col;
std::vector<int> rowPascal = pascal(row,std::vector<int>{1});
std::cout<< rowPascal[col];
}
With the driver function to test. I know it's not very efficient but it should do!
This will basically give you the number at a specific row ( from the top) and a specific col (from the left) in the pascal's triangle . (both zero indexed)
Given that it's unreasonably difficult to print the triangle without using loops, here is a solution that uses your purely recursive Pascal_Tri function to compute the numbers but prints them with a loop:
int rowsToPrint = 5;
for (int row = 0; row < rowsToPrint; ++row)
{
for (int col = 0; col <= row; ++col)
std::cout << Pascal_Tri(row, col) << ", ";
std::cout << std::endl;
}
Demo

How to display minimum spannign tree matrix

#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include<iomanip>
using namespace std;
typedef pair<int, int> intPair;// rename intPair
typedef vector<double> doubleVector; //rename doubleVetcor
typedef vector<intPair> intPairVector; // rename intPairVector
// Union-Find Disjoint Sets Library written in OOP manner, using both path compression and union by rank heuristics
class UnionFind { // OOP style
private:
doubleVector p, rank, setSize; // remember: vi is vector<double>
int numSets;
public:
UnionFind(int N) {
setSize.assign(N, 1);
numSets = N;
rank.assign(N, 0);
p.assign(N, 0);
for (int i = 0; i < N; i++)
p[i] = i;
}
int findSet(int i) {
return (p[i] == i) ? i : (p[i] = findSet(p[i]));
}
bool isSameSet(int i, int j) {
return findSet(i) == findSet(j);
}
void unionSet(int i, int j) {
if (!isSameSet(i, j)) {
numSets--;
int x = findSet(i), y = findSet(j);
// rank is used to keep the tree short
if (rank[x] > rank[y]) {
p[y] = x;
setSize[x] += setSize[y];
}
else{
p[x] = y;
setSize[y] += setSize[x];
if (rank[x] == rank[y])
rank[y]++;
}
}
}
int numDisjointSets() {
return numSets;
}
int sizeOfSet(int i) {
return setSize[findSet(i)];
}
};
vector<intPairVector> AdjList;
int main() {
int num_verts=0;
cin >> num_verts;
//Pre-allocate a vector of num_verts rows, each of which is a vector
//of num_verts copies of 0.0
vector<vector<double>> matrix(num_verts, vector<double>(num_verts,0.0));
//Requires c++11 or higher
for(int row = 0; row<num_verts;++row) {
for(int col = 0; col<num_verts; ++col){
cin >> matrix[row][col];
}
}
//print out the matrix we just read
for(int row = 0; row<num_verts; ++row) {
for(int col=0; col<num_verts;++col){
cout << setprecision(2) << fixed << matrix[row][col] << "\t";
}
cout << "\n";
}
// Kruskal's algorithm merged
AdjList.assign(num_verts, intPairVector());
vector< pair<double, intPair> > EdgeList; // (weight, two vertices) of the edge
for (int row = 0; row<num_verts; ++row) {
for(int col=0; col<num_verts;++col){
EdgeList.push_back(make_pair(matrix[row][col], intPair(row,col)));
AdjList[row].push_back(intPair(row,matrix[row][col]));
AdjList[col].push_back(intPair(col,matrix[row][col]));
}
}
sort(EdgeList.begin(), EdgeList.end()); // sort by edge weight O(E log E)
// note: pair object has built-in comparison function
double mst_cost = 0.0;
UnionFind UF(num_verts); // all V are disjoint sets initially
for (int i = 0; i < num_verts*num_verts; i++) { // for each edge, O(E)
pair<double,intPair> front = EdgeList[i];
if (!UF.isSameSet(front.second.first, front.second.second)) { // check
mst_cost += front.first; // add the weight of e to MST
UF.unionSet(front.second.first, front.second.second); // link them
}
} // note: the runtime cost of UFDS is very light
//display the weight of the MST
cout << setprecision(2) << fixed << mst_cost << endl;
return 0;
}
I am trying to display the minimum spanning tree from this code, I cannot figure out how to get this code to display the modified matrix. The code is working correctly, by that I mean it is compiling and calculating the correct weight for the graph. However, I am unsure how to display the minimum spanning tree from using Kruskals algorithm. Thanks for any help
Whenever you add the weight of an edge to the weight of the MST, you should also add that edge to a list to keep track of the MST edges.

Using Dijkstra algorithm to compute shortest path between two nodes

I am new in C++. I am trying to compute the path to travel from node start to node end using Dijkstra algorithm. I am pretty sure I am computing the shortest path in the correct way but for some reason I can't store it in my traceBack vector. It would be really helpful if anyone would help me pointing my mistake here.
My function descriptions and the part of the code where I am computing the shortest path is the following:
The function find_connected_nodes(int x) returns only the nodes connected to the given node.
the function find_travel_time(int x, int y) returns the time to travel from x to y.
void dijkstra(int start, int end) {
vector <unsigned> visited(getNumberOfNodes(), 0);
vector <double> time_weight(getNumberOfNodes(), 99999); //99999 to represent not connected
int inNode = start, pathNode = _end, nextnode = 0;
double min; //will use min to compare time between edges
vector<unsigned> traceBack(getNumberOfNodes(), inNode); //traceBack to contain the path from start to end
time_weight[inNode] = 0;
visited[inNode] = 1;
vector<unsigned> x = find_connected_nodes(start);
if (!x.empty()) {
for (unsigned i = 0; i < x.size(); i++) {
time_weight[x[i]] = find_travel_time(start, x[i]));
}
}
for (int i = 0; i < getNumberOfNodes(); i++) {
min = 99999;
for (int j = 0; j < x.size(); j++) {
if (min > time_weight[x[j]] && visited[x[j]] != 1) {
min = time_weight[x[j]];
nextnode = x[j];
}
}
visited[nextnode] = 1;
for (int j = 0; j < x.size(); j++) {
if (visited[x[j]] != 1) {
if (min + find_travel_time(nextnode, x[j]))<time_weight[x[j]]) {
time_weight[x[j]] = min + find_travel_time(nextnode, x[j]));
traceBack[x[j]] = nextnode;
}
}
}
x = find_connected_nodes(nextnode);
}
int j;
cout << "Path = " << pathNode;
j = pathNode;
do {
j = traceBack[j];
cout << "<-" << j;
} while (j != inNode);
}
Not a complete solution to your problem, because it’s homework and you’ll want to solve it on your own, but here is an example of how to solve the same kind of design problem you’re dealing with:
#include <cstdlib>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::size_t;
std::vector<double> map_squares( const std::vector<double>& inputs )
/* Maps the square function onto the inputs. That is, returns a vector whose
* elements are the squares of the input elements.
*/
{
const size_t size = inputs.size(); // The number of inputs, and outputs.
std::vector<double> outputs(size); // We will return this.
/* (Actually, we will return a copy of the vector, and then the compiler will
* optimize the copy so it doesn't have to copy every element, just a single
* reference to the data in the vector. You'll learn more about how that
* works, and how to write classes like that yourself, in due time.)
*/
for ( size_t i = 0; i < size; ++i ) {
outputs[i] = inputs[i]*inputs[i];
}
outputs.shrink_to_fit(); // Maybe save a few bytes of memory.
return outputs;
}
std::ostream& operator<<( std::ostream& os, const std::vector<double>& v )
// Boilerplate to serialize and print a vector to a stream.
{
const size_t size = v.size();
os << '[';
if (size > 0)
os << v[0];
for ( size_t i = 1; i < size; ++i )
os << ',' << v[i];
os << ']';
return os;
}
int main(void)
{
// Out inputs:
const std::vector<double> raw_numbers = {4,2,1,0.5,0.25};
// Our results:
const std::vector<double> squares = map_squares(raw_numbers);
// Output: "[16,4,1,0.25,0.0625]"
cout << squares << endl;
return EXIT_SUCCESS;
}

generate unique numbers to 2-Dimensional array using linear search

The program compiles and I can enter a number, but it doesn't generate or it display the array. When I take out the while condition with the linear search in the randomFillUnique function, it generates and displays the array, but not unique numbers. I needed a 2D array with no duplicate numbers.
#include <iostream>
#include <string>
#include <random>
#include <ctime>
using namespace std;
int** gen2Array(int n);
void randomFillUnique(int** arr, int n);
bool lSearch(int** arr, int n, int target);
void display(int** arr, int n);
int main()
{
int number;
cout << "Enter a number: ";
cin >> number;
randomFillUnique(gen2Array(number), number);
system("pause");
return 0;
}
int** gen2Array(int n)
{
int** arr2D = new int*[n];
for (int index = 0; index < n; index++)
arr2D[index] = new int[n];
return arr2D;
}
void randomFillUnique(int** arr, int n)
{
static default_random_engine e;
uniform_int_distribution<int> u(1, n*n);
e.seed(static_cast<int>(time(NULL)));
bool result = false;
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
{
arr[row][col] = u(e); //generate random number
result = lSearch(arr, n, arr[row][col]);
while (result == true)
{
arr[row][col] = u(e); //generate random number
result = lSearch(arr, n, arr[row][col]);
}
}
}
display(arr, n);
delete[] arr;
}
bool lSearch(int** arr, int n, int target)
{
bool found = false;
for (int row = 0; row < n; row++)
for (int col = 0; col < n; col++)
{
if (arr[row][col] == target)
{
found = true;
return found;
}
}
return found;
}
void display(int** arr, int n)
{
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
cout << arr[row][col];
cout << endl;
}
}
Because you are setting the entry in the array to u(e) before you lsearch, lsearch always returns true and your while loops forever. The below, adapted from your code, should fix that (I am assuming the rest of the code behaves as one would expect). As user4581301 points out, there may be better approaches, but I am going with yours enough to get it working, I hope.
void randomFillUnique(int** arr, int n)
{
static default_random_engine e;
uniform_int_distribution<int> u(1, n*n);
e.seed(static_cast<int>(time(NULL)));
int nextEntry;
bool result = false;
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
{
result = true;
while (result == true)
{
nextEntry = u(e); //generate random number
result = lSearch(arr, n, nextEntry);
if (result != true)
{arr[row][col]=nextEntry;}
}
}
}
display(arr, n);
delete[] arr;
}
An alternative approach would be to create a container of all the unique integers which will go into the array, using iota:
std::vector<int> invalues(n*n, 0);
std::iota(invalues.begin(), invalues.end(), 1);
Then shuffle that container:
std::shuffle(invalues.begin(), invalues.end(),
std::mt19937{std::random_device{}()});
Then feed the values one by one into the matrix.
You could also use a vector<vector<int>> instead of built-in arrays:
using matrix = std::vector<std::vector<int>>;
// initialising a vector<vector<int>> to be a certain size is a bit clumsy
matrix m(size_y, std::vector<int>(size_x, 0));
Then feeding the input values into the matrix:
for (auto &row : m) {
for (auto &elem : row) {
elem = invalues.back();
invalues.pop_back();
}
}
Then displaying the matrix:
for (const auto &row : m) {
for (const auto &elem : row) {
std::cout << elem << " ";
}
std::cout << std::endl;
}
Here's a full example in an online compiler.
OK. Here's the easier way to do this I commented on. If std::vector is disallowed, a simple 1D vector will suffice, but a sane software engineer would think really, really hard before selecting it over a vector.
I made a few other changes to fix a couple other bugs.
#include <iostream>
#include <string>
#include <random>
#include <vector>
#include <algorithm> // std::shuffle and std::iota
#include <ctime>
using namespace std;
int** gen2Array(int n);
void randomFillUnique(int** arr, int n);
bool lSearch(int** arr, int n, int target);
void display(int** arr, int n);
//Added to properly delete the 2dArray
void del2Array(int ** arr, int n);
int main()
{
int number = 10;
randomFillUnique(gen2Array(number), number);
system("pause");
return 0;
}
int** gen2Array(int n)
{
int** arr2D = new int*[n];
for (int index = 0; index < n; index++)
arr2D[index] = new int[n];
return arr2D;
}
//Added to properly delete the 2dArray
void del2Array(int ** arr,
int n)
{
for (int index = 0; index < n; index++)
delete arr[index];
delete arr;
}
void randomFillUnique(int** arr, int n)
{
//do the seeding here
static default_random_engine e(static_cast<int>(time(NULL)));
// otherwise
// e.seed(static_cast<int>(time(NULL)));
// runs every time reseeding the RNG to potentially the give the same results
// if run more than once in a second. Plus the seeding is expensive.
std::vector<int> v(n*n); // make and size vector
std::iota (v.begin(), v.end(), 0); // init vector with 1 through n*n
std::shuffle(v.begin(), v.end(), e);
size_t index = 0;
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
{
arr[row][col] = v[index++]; //generate random number
}
}
display(arr, n);
del2Array (arr, n); // frankly I don't think you want his here
// why fill an array only to delete it?
// more logical to display and delete back in main.
}
void display(int** arr, int n)
{
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
cout << arr[row][col] << "\t"; //added a tab to make the printing easier to read
cout << endl;
}
}
Documentation on std::vector
Documentation on std::shuffle
Documentation on std::iota. Which uses exactly this technique to demonstrate iota. Funny, huh?