Maximum matching in a graph - c++

I have an interesting problem:
My program must to find the maximum number of 1.
But that's not all!.
If the program has "seen" 1, then it should clear the entire column and row in which the 1 is located.
The problem I have:
I can not find the maximum number of 1, I do not know how to do that.
For you I made a small example, I hope it will be clear to you. The program must work like this:
There is a matrix:
1 0 0 0
1 0 1 1
1 1 1 1
1 0 0 1
The program found 1 (position [0][0] I've highlighted it in black), and cleared the row and column:
After this we find the next 1, cleared the row and columnand so on:
At the end, the program should print the number of black cells.
In my example it's 4
How to do it in C++ code? Please help me! Thank you.

I prefer to do it like this (see code below): Use two "for" loops and inside the second use conditional "if" to add the third "for" loop to set to 0.
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
{
if(cow[j][i]==1)
{
cnt++;
for(int k=0;k<n;k++)
cow[k][i]=cow[j][k]=0;
break;
}
}

it's not clear how you search for the 'next' 1 in your matrix and if the matrix can only contain 0 and 1. But if there is a clear definition of what 'next' is, then you just code exactly as you have described it above. A possible code snippet looks like this (not tested, not even compiled):
bool find_next_one(int&x, int&y, matrix const&M)
{
// next is in (col,row) order
for(; x!=M.size(0); ++x)
for(; y!=M.size(1); ++y)
if(M(x,y)==1) return 1;
return 0;
}
int count_one(matrix const&M_original)
{
matrix M(M_original); // make copy where we can set elements to 0
int count=0;
int x=0,y=0;
while(find_next_one(x,y,M)) {
++count;
for(int i=0; i!=M.size(1); ++i) M(x,i) = 0;
for(int i=0; i!=M.size(0); ++i) M(i,y) = 0;
}
return count;
}

Noticed this looks like a matrix singularity type check - especially if 1s and 0s are the only thing to be used.
You can check the determinate of the matrix. Non zero means it is equal to the number of rows and columns (if the matrix is always square.) If det(0), then use any technique you want to bring the matrix down to reduced form to see how many 0'd columns you have - or just do the reduction first and walk down the diagonal counting.
Heck sorting the columns by their added value, will put it in diagonal form for you. That would make it pretty easy also to check for 0 columns.

I won't write all the code for you, but will suggest some things to get you on track. You should understand how to iterate over a two dimensional array (the matrix) and also how to iterate over a single row or column within that matrix.
Given a (hard coded) definition of matrix that looks like this:
struct Matrix4x4
{
int m[4][4];
};
To iterate over all elements you want to write something like this:
Matrix4x4 matrix;
for (size_t row = 0; row < 4; ++row)
{
for (size_t col = 0; col < 4; ++col)
{
// do something with 'matrix.m[row][col]'
}
}
This will iterate over your matrix from top left (0,0) to bottom right (3,3). I am assuming that this is the traversal order you have been told to use.
To process a row you want to write something like this:
void FunctionThatOperatesOnARow(Matrix4x4& matrix, size_t row)
{
for (size_t col = 0; col < 4; ++col)
{
// do something with 'matrix.m[row][col]'
}
}
To process a column you want to write something like this:
void FunctionThatOperatesOnAColumn(Matrix4x4& matrix, size_t col)
{
for (size_t row = 0; row < 4; ++row)
{
// do something with 'matrix.m[row][col]'
}
}
What you need to do now is modify the first bit of code that iterates over all elements and get it to check for a 1. You then need to call the appropriate functions to clear the current column and row (which you can base on the latter two examples).
For the final result you can simply increment a local counter variable each time you detect a 1.

Related

c++ Sudokou Grid initialisation

So I'm very new to c++, studying it at present and have a piece of work to do that's stumping me. You guys are the first port of call.
I need to make what is essentially a 2d array of objects. The header file includes Cell objects for rows, columns and blocks. The idea that I have a 9x9 array of objects, with relevant pointers based on column, row and internal 3x3 block therein. What I'm stuck on is that the below line fills out the 9x9 but how am I pointing to each Cell?
Or is that in something separate and this is all I need to do for just setting up that grid??
void SudokuPuzzle::InitialiseGrid()
{
for (int row = 0; row < 9; row++)
{
for (int column = 0; column < 9; column++)
{
m_gridRows[row].SetCell(column, new SudokuSquare());
// have the cell point to both it's position in the column and block
}
}
}
Maybe try to create the 2d array of the Type "SudokuSquare".
SudokuSquare sSquare [9][9];
So you can acces any object by
sSquare[row][column];
If your array is fixed size e.g. 3x3 just use std::array:
#include <array>
using std::array;
int main()
{
array<array<int, 3>, 3> sudoku_squares{};
sudoku_squares[0][1] = 1; // sets cell at first row, second column to 1
return 0;
}
In your case you can store 9 of those 3x3 arrays in another array or just use 9x9 array and you don't need to use any pointers. I used int in my example but you can store SudokuSquare exactly the same way.

Parallelization false sharing Openmp

I have a matrix of integers, for example:
1 0 1
2 1 0
1 1 1
This is a trivial example; my problem is much larger than this example (think 2000 x 2000). I have to modify the matrix following this rules: I have to do two steps: (1) If the element below a 1 in my matrix is 0, then my move should be "1", and then (2) if the element to the right of a 2 in my matrix is 0, my move should be "2".
I'm using two vectors to save the positions of ones and twos. These vectors are std::vector<triplet> where triplet is a struct made to handle the problem:
struct triplet{
int row, column, move;
};
So each element of vector1 contains the position of 1 (row and column) and the variable move (that is 0 or 1) to show me if I can move the associated 1.
I do the same with vector 2 separately.
void modifyvector1(vector<vector<int>>& matrix,vector<triplet>& vector1,int nrow,int ncolumn)
{
#pragma omp parallel for
for (int scorriblu = 0; scorriblu < vector1.size(); scorriblu++) {
int i = vector1[scorriblu].row;
int j = vector1[scorriblu].column;
vector1[scorriblu].move = 0;
if(i != nrow) {
if (matrix[i+1][j] == EmptySpace) {
vector1[scorriblu].move = 1;
}
}
else {
if (matrix[0][j] == EmptySpace) {
vector1[scorriblu].move = 1;
}
}
}
}
However, this program is slower than serial. I think that the main problem is that each thread is trying to access the matrix that is stored in shared memory and this is causing a huge rallenty. But I am not sure that this is the problem, and how to fix it.
Sorry for my explanation but I'm new with C++ and OpenMP.

3D Array to 3D std::vector

I replaced a 3D array with a 3D std::vector in my code function and it's entering a infinite loop .Could you give me a hint,I really need to use a vector instead an array.Thanks:)
My initial code was:
//arr is a 3D array of a sudoku table,the 3 rd dimension is for keeping values 0 to 13
//for a cell, and when I assign values I start from index 1 to 12
bool sol(int arr[12][12][13]) {
int row,col;
if(!find_empty(arr,row,col)) return true;
for(int i=1;i< 12;i++) { //for digits 1 to 12
if(is_working(arr,row,col,arr[row][col][i]) ) { //if i can put the value in a cell
arr[row][col][0] = arr[row][col][i]; //replace the first element for a cell with that value
//here I want to use vector because I want to use an ac3 algorithm
//and remove those values that not satisfy constraints and shrink domain size having less values to verify with backtrack
if(sol(arr)) return true;
arr[row][col][0] = 0;
}
}
return false;//if not backtrack
}
I replace arr with:
std::vector<std::vector<std::vector<int> > > vec;
vec.resize(12);
for(int i=0;i<12;i++)
{
vec[i].resize(12);
for(int j=0;j<12;j++)
{
vec[i][j].resize(13);
for(int k=0;k<13;k++)
vec[i][j][k]=table[i][j][k];
}
}
bool sol(std::vector<std::vector<std::vector<int> > >& vec) {
int row,col;
if(!find_empty(vec,row,col)) return true;
for(int i=1;i< vec[row][col].size();i++) {//for remainig values in domain
if(is_working(vec,row,col,vec[row][col][i]) ) {//same as above but having less values to verify for
vec[row][col][0] = vec[row][col][i];
if(sol(vec)) return true;
vec[row][col][0] = 0;
}
}
return false;
}
and now it's entering a infinite loop!The initial code has no errors,it's a simple backtracking.The problem appears after I replace arr with vec.Could you give me some advice on how to replace 3D arr with an 3D vector
Your question is not clear enough. If you can also post the code for is_working and find_empty, then we would be able to see how you are getting the values of row and column.
I would have put this as a comment but being a new member and not having enough reputations, I have to put this as an answer. I'll edit it once you share the code for is_working() and find_empty()
I have solved the problem. I used a matrix of vectors instead a 3D vector and it works great :D
maybe this better for 3d one, 4x4x4
std::vector<std::vector<std::vector<double>>> matrix;
matrix.resize(4, std::vector<std::vector<double>>(4,std::vector<double(4)));

C++ Array Sum Values Around Coordinate

I'm having some difficulty summing the values of a multidimensional array around the coordinates given below. Something is wrong with my logic with the index location. Any ideas would be very helpful and if more information is needed, please don't hesitate to ask me.
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
srand(time(0));
int displayArray[11][11];
cout<<"\t\t\t\t\t\t\t\t\t\t\t\t\tColumn\n\n";
for(int column=1;column<10;column++)
{
cout<<"\t "<<column;
}
cout<<"\n\n";
//fill array with random numbers
for(int i=0;i<9;i++)
{
for(int m=0;m<9;m++)
{
displayArray[i][m]=rand()%10;
}
}
cout<<"\n\n\n";
//main data printout
for(int k=0;k<9;k++)
{
cout<<"Row "<<k+1<<"\t ";
for(int l=0;l<9;l++)
{
cout<<displayArray[k][l]<<"\t";
}
cout<<endl<<endl;
}
cout<<"\n\n";
int row=0, column=0;
cout<<"What array cell would you like to see? (Press enter after each entry)\n";
cout<<"Row = ";
cin>>row;
cout<<"Column = ";
cin>>column;
cout<<"\nThe number "<<displayArray[row-1][column-1]<<" is in cell "<<row<<","<<column;
int coord1=displayArray[row-2][column+2],
coord2=displayArray[row+2][column+2],
coord3=displayArray[row-2][column-2],
coord4=displayArray[row-2][column+2],
coord5=displayArray[row-2][column+2],
coord6=displayArray[row-2][column+2],
coord7=displayArray[row-2][column+2],
coord8=displayArray[row-2][column+2];
int sum=coord1+coord2+coord3+coord4+coord5+coord6+coord7+coord8;
cout<<"\n\nThe sum of the cells surrounding "<<row<<","<<column<<" is "<<sum;
cin.get();
cin.get();
return 0;
}
Your problem may be that you are using row/column -2 and row/column +2 as your adjacent directions, which is not correct. If (row-1, col-1) is your current cell, than you want row/col -2 and row/col +0.
int coord1=displayArray[row-2][column-2],
coord2=displayArray[row-2][column-1],
coord3=displayArray[row-2][column],
coord4=displayArray[row-1][column-2],
coord5=displayArray[row-1][column],
coord6=displayArray[row][column-2],
coord7=displayArray[row][column-1],
coord8=displayArray[row][column];
int sum=coord1+coord2+coord3+coord4+coord5+coord6+coord7+coord8;
This can be done much more programmatically, however:
int sum = 0;
for (int x=row-2; x<=row; x++) {
for (int y=column-2; y<=column; y++) {
if ((x != row-1) || (y != column-1)) { //Avoids "center" cell (self)
sum += displayArray[x][y]
}
}
}
So if I'm understanding this correctly, the user inputs a row and column number, which corresponds to the value located in displayArray[row-1][column-1]
Thus, the coordinates around that cell should be.
displayArray[row][column]
displayArray[row-1][column]
displayArray[row-2][column]
displayArray[row][column-1]
displayArray[row-2][column-1]
displayArray[row][column-2]
displayArray[row-1][column-2]
displayArray[row-2][column-2]
I'm not sure exactly why you're using the coordinates you are, but that is your problem.
Also, you're going to want to make sure your program doesn't crash if the user selects a cell on the border of the array. eg: If you try to search coordinates around the cell (0,0), the program will crash when trying to load a value for displayArray[-1][-1]
Your mistake is in translating 0 based to 1 based indexing. The arrays are 0 based. You're having them enter in a 1 based row. Then you want to add the 8 numbers around it. If they entered 0 based numbers and entered N, you'd want to sum [n-1], n, and n+1 for each row/column. To deal with 0 based, you want to do n-2, n-1, and n. But you're doing n-2 and n+2. You're also not calculating the middle of the rows anywhere near right.
Best practice is not even to do the math like that. It would be to read in the row/column number, then immediately subtract 1 to make it 0 based, and deal with it as 0 based from then on.

How to efficiently change a contiguous portion of a matrix?

Given a matrix of M rows and N columns, and allocated as a byte array of M*N elements (these elements are initially set to zero), I would modify this matrix in according to the following rule: the elements that are found in the neighborhood of a certain element must be set to a given value. In other words, given a matrix, I should set a region of the matrix: for this purpose I should access not contiguous portion of the array.
In order to perform the above operation, I have access to the following information:
the pointer to the element that is located in the center of the neighborhood (this pointer must not be changed during the above operation); the position (row and column) of this element is also provided;
the size L*L of the neighborhood (L is always an odd number).
The code that implements this operation should be executed as fast as possible in C++: for this reason I thought of using the above pointer to access different pieces of the array. Instead, the position (row and column) of the central element of the neighborhood could allow me to check whether the specified region exceeds the dimensions of the matrix (for example, the center of the region may be located on the edge of the matrix): in this case I should set only that part of the region that is located in the matrix.
int M = ... // number of matrix rows
int N = ... // number of matrix columns
char* centerPtr = ... // pointer to the center of the region
int i = ... // position of the central element
int j = ... // of the region to be modified
char* tempPtr = centerPtr - (N+1)*L/2;
for(int k=0; k < L; k++)
{
memset(tempPtr,value,N);
tempPtr += N;
}
How can I improve the code?
How to handle the fact that one region may exceeds the dimensions of a matrix?
How to make the code more efficient with respect to the execution time?
Your code is probably optimal for the general case where the region does not overlap the outside of the matrix. The main efficiency problem you can cause with this kind of code is to make the outer loop over columns instead of rows. This destroys cache and paging performance. You haven't done that.
Using pointers has little or no speed advantage with most modern compilers. Optimizers will come up with very good pointer code from normal array indices. In some cases I've seen array index code run substantially faster than hand-tweaked pointer code for the same thing. So don't use pointer arithmetic if index arithmetic is clearer.
There are 8 boundary cases: north, northwest, west, ..., northeast. Each of these will need a custom version of your loop to touch the right elements. I'll show the northwest case and let you work out the rest.
The fastest possible way to handle the cases is a 3-level "if" tree:
if (j < L/2) { // northwest, west, or southwest
if (i < L/2) {
// northwest
char* tempPtr = centerPtr - (L/2 - i) * N - (L/2 - j);
for(int k = 0; k < L; k++) {
memset(tempPtr, value, L - j);
tempPtr += N;
}
} else if (i >= M - L/2) {
// southwest
} else {
// west
}
} else if (j >= N - L/2) { // symmetrical cases for east.
if (i < L/2) {
// northeast
} else if (i >= M - L/2) {
// southeast
} else {
// east
}
} else {
if (i < L/2) {
// north
} else if (i >= M - L/2) {
// south
} else {
// no overlap
}
}
It's tedious to do it like this, but you'll have no more than 3 comparisons per region.