Painting rows and columns of a 2D matrix - c++

Problem: We have given a nxm matrix, initially initialized with 0. We have to perform k queries:
Each query supports one of the two operations.
paint all elements in ri row with the colour ai .
paint all elements in ci column with the colour ai.
The same element can be painted more than once. But the color of that element is the same as the last painted colour for that element. You have to print the final matrix after painting.
Input: The first line contains three space-separated integers N,M,K
Next K lines consist of exactly one typep of operation to be performed
1) 1 ri ai means row ri is painted with color ai
2) 2 ci ai means column ci is painted with color ai
Output: Print the final matrix of size nxm after painting.
Sample Input: 3 3 3
1 1 3 2 2 1 1 2 2 Output: 3 1 3 2 2 2 0 1 0
I have written the following code to solve it but it is showing TLE for some test cases. Can you give me some idea how to solve it in efficient way?
My Code
#include<bits/stdc++.h>
#define ll long long int
using namespace std;
int mat[5000][5000];
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
int n,m,k,q,r,c,val,i,j,re;
cin>>n>>m>>re;
while(re--)
{
cin>>q;
if(q==1)
{
cin>>r;
cin>>val;
i=r-1;
for(j=0,k=m-1;j<=k;j++,k--)
{
mat[i][j]=val;
mat[i][k]=val;
}
}
else if(q==2)
{
cin>>c>>val;
j=c-1;
for(i=0,k=n-1;i<=k;i++,k--)
{
mat[i][j]=val;
mat[k][j]=val;
}
}
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
cout<<mat[i][j]<<" ";
}
cout<<endl;
}
}

It is only needed to memorize the last color that was affected to a given row or a given column, and the last time at which it was performed.
Then, for a given element mat[i][j], we simply have to check if the last modification on row i occured before of after the last modification on column j.
We don't even need to set such a matrix.
#include <iostream>
#include <ios>
#include <vector>
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(0);
int n, m, re;
std::cin >> n >> m >> re;
std::vector<int> row_color (n, 0), row_date (n, -1);
std::vector<int> col_color (m, 0), col_date (m, -1);
int date = 0;
while (re--) {
int q, index, val;
std::cin >> q >> index >> val;
index--;
if (q == 1) {
row_color[index] = val;
row_date[index] = date;
} else {
col_color[index] = val;
col_date[index] = date;
}
++date;
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
int val = (row_date[i] > col_date[j]) ? row_color[i] : col_color[j];
std::cout << val << " ";
}
std::cout << "\n";
}
}

Instead of performing all the paint operations as they come in, you could:
While parsing the input, keep and update:
For each row the last color ai it is supposed to be painted in and the corresponding value k (running from 0 to K)
The same for each column
Setup an array of paint operations that combines both row and column paintings for all rows, columns where a painting occured
Sort the array based on k
Perform these operations on a matrix initialized with 0
This algorithm has an advantage if there is a large k (so, lots of overpainting) which you could expect from these kind of problems.

Related

Finding all possible combinations with 1 element in each row of a 2D array

Recently I have been trying to do a problem that requires me to find all the different combinations with selecting only 1 element from each row. For example, I'm inputting n rows with 2 strings per row. However, I only want to find all the different combinations where I choose 1 string from each row.
Example:
Input:
3
alex bob
straw mat
eat drink
Example combination:
alex straw drink
This results in 2^n combinations, which in this case would be 2^3 = 8 combinations. However, if I was to use n for loops to find the combinations
e.g.
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int n;
int main(int argc, char ** argv) {
cin >> n; //rows of words
string words[n][2]; //the words with 2 words per row
for (int i = 0; i < n; i++) {
for (int j = 0; j < 2; j++) {
cin >> words[i][j]; //input of words
}
}
//finding all possible combinations
for (int i =0; i<n; i++){
for (int j=0; j<2; j++){
for (int x=0; x<2; x++){
//and so on per n
}
}
}
return 0;
}
this would take n for loops to find out all the combinations of the array with only taking one item from each row. What would be the best and simplest approach to finding all different combinations with size n as I would take 1 string out of the two in each row? Thanks.
You can do recursion.
Assuming C++11, something like this maybe (didn't try to compile this though):
// finding all possible combinations
std::vector<std::vector<std::string>> combinations;
const auto processLine = [&](const std::vector<std::string>& currentCombination, int line) {
std::vector<std::string> combination0 = currentCombination;
std::vector<std::string> combination1 = currentCombination;
combination0.push_back(words[line][0]);
combination1.push_back(words[line][1]);
if (line + 1 < n) {
// process next line
processLine(combination0, line + 1);
processLine(combination1, line + 1);
}
else {
// last line - keep the result
combinations.push_back(combination0);
combinations.push_back(combination1);
}
};
std::vector<std::string> empty;
processLine(empty, 0);
// print results
for (const auto& combination : combinations) {
for (const auto& word : combination) {
std::cout << word << " ";
}
std::cout << std::endl;
}
A very simple solution for a setting where you have always 2 elements per row would be to use datatype integer and interpret each bit as a decision for the first or the second column in the respective row; then simply count from 0 to 2^n - 1 in order to get all combinations.
Applied to your example this would look as follows:
int bits meaning
0 000 alex,straw,eat
1 001 alex,straw,drink
2 010 alex,mat,eat
3 011 alex,mat,dring
4 100 bob,straw,eat
5 101 bob,straw,drink
6 110 bob,mat,eat
7 111 bob,mat,drink
For any of the given integer values 0..7, use bit shift operators or &-bitmask to map each bit to a column index:
void getCombinationRepresentedByIntValue(vector<string>& combination, int value) {
int mask = 1;
for (int i=n-1; i>=0; i--) {
if (value & mask)
combination.push_back(words[i][1]);
else
combination.push_back(words[i][0]);
mask = mask << 1;
}
}
That seems to answer your question :
int ct[n]; // count of the number of pass
int current = 0; // index of the current word (n)
/* while not all combinaison have been exploited */
while (current >= 0)
{
cout << words[current][ct[current]]; /* <<<<< can be used another way*/
/* down to the next word */
current ++; // to get the next word
if (current >=n) { // at the end of the list
cout << " ";
current--; // restore last
ct[current]++; // increment number of time we passed
/* find the previous not completely exploited */
while (current >= 0 && ct[current]> 1) /* <<< change 1 to any number of words per line */
{
ct[current] = 0;
current--;
if (current >= 0) ct[current]++;
}
if (current > 0 ) current = 0;
}
}
With your example :
Input :
3
alex bob
straw mat
eat drink
output :
alexstraweat
alexstrawdrink
alexmateat
alexmatdrink
bobstraweat
bobstrawdrink
bobmateat
bobmatdrink
hope it helps !

Algorithm to divide a black-and-white chocolate bar

Problem description:
There's a chocolate bar that consists of m x n squares. Some of the squares are black, some are white. Someone breaks the chocolate bar along its vertical axis or horizontal axis. Then it is broken again along its vertical or horizontal axis and it's being broken until it can broken into a single square or it can broken into squares that are only black or only white. Using a preferably divide-and-conquer algorithm, find the number of methods a chocolate bar can be broken.
Input:
The first line tells you the m x n dimensions of the chocolate bar. In the next m lines there are n characters that tell you how does the chocolate bar look. Letter w is a white square, letter b is a black square.
for example:
3 2
bwb
wbw
Output:
the number of methods the chocolate bar can be broken:
for the example above, it's 5 (take a look at the attached picture).
I tried to solve it using an iterative approach. Unfortunately, I couldn't finish the code as I'm not yet sure how to divide the the halves (see my code below). I was told that an recursive approach is much easier than this, but I have no idea how to do it. I'm looking for another way to solve this problem than my approach or I'm looking for some help with finishing my code.
I made two 2D arrays, first for white squares, second for black squares. I'm making a matrix out of the squares and if there's a chocolate of such or such color, then I'm marking it as 1 in the corresponding array.
Then I made two arrays of the two cumulative sums of the matrices above.
Then I created a 4D array of size [n][m][n][m] and I made four loops: first two (i, j) are increasing the size of an rectangular array that is the size of the searching array (it's pretty hard to explain...) and two more loops (k, l) are increasing the position of my starting points x and y in the array. Then the algorithm checks using the cumulative sum if in the area starting at position kxl and ending at k+i x l+j there is one black and one white square. If there is, then I'm creating two more loops that will divide the area in half. If in the two new halves there are still black and white squares, then I'm increasing the corresponding 4D array element by the number of combinations of the first halve * the number of combinations of the second halve.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int counter=0;
int n, m;
ifstream in;
in.open("in.txt");
ofstream out;
out.open("out.txt");
if(!in.good())
{
cout << "No such file";
return 0;
}
in >> n >> m;
int whitesarray[m][n];
int blacksarray[m][n];
int methodsarray[m][n][m][n];
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
whitesarray[i][j] = 0;
blacksarray[i][j] = 0;
}
}
while(in)
{
string colour;
in >> colour;
for (int i=0; i < colour.length(); i++)
{
if(colour[i] == 'c')
{
blacksarray[counter][i] = 1;
}
if(colour[i] == 'b')
{
whitesarray[counter][i] = 1;
}
}
counter++;
}
int whitessum[m][n];
int blackssum[m][n];
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
{
if(i-1 == -1 && j-1 == -1)
{
whitessum[i][j] = whitesarray[i][j];
blackssum[i][j] = blacksarray[i][j];
}
if(i-1 == -1 && j-1 != -1)
{
whitessum[i][j] = whitessum[i][j-1] + whitesarray[i][j];
blackssum[i][j] = blackssum[i][j-1] + blacksarray[i][j];
}
if(j-1 == -1 && i-1 != -1)
{
whitessum[i][j] = whitessum[i-1][j] + whitesarray[i][j];
blackssum[i][j] = blackssum[i-1][j] + blacksarray[i][j];
}
if(j-1 != -1 && i-1 != -1)
{
whitessum[i][j] = whitessum[i-1][j] + whitessum[i][j-1] - whitessum[i-1][j-1] + whitesarray[i][j];
blackssum[i][j] = blackssum[i-1][j] + blackssum[i][j-1] - blackssum[i-1][j-1] + blacksarray[i][j];
}
}
}
int posx=0;
int posy=0;
int tempwhitessum=0;
int tempblackssum=0;
int k=0, l=0;
for (int i=0; i<=m; i++)
{
for (int j=0; j<=n; j++) // wielkosc wierszy
{
for (posx=0; posx < m - i; posx++)
{
for(posy = 0; posy < n - j; posy++)
{
k = i+posx-1;
l = j+posy-1;
if(k >= m || l >= n)
continue;
if(posx==0 && posy==0)
{
tempwhitessum = whitessum[k][l];
tempblackssum = blackssum[k][l];
}
if(posx==0 && posy!=0)
{
tempwhitessum = whitessum[k][l] - whitessum[k][posy-1];
tempblackssum = blackssum[k][l] - blackssum[k][posy-1];
}
if(posx!=0 && posy==0)
{
tempwhitessum = whitessum[k][l] - whitessum[posx-1][l];
tempblackssum = blackssum[k][l] - blackssum[posx-1][l];
}
if(posx!=0 && posy!=0)
{
tempwhitessum = whitessum[k][l] - whitessum[posx-1][l] - whitessum[k][posy-1] + whitessum[posx-1][posy-1];
tempblackssum = blackssum[k][l] - blackssum[posx-1][l] - blackssum[k][posy-1] + blackssum[posx-1][posy-1];
}
if(tempwhitessum >0 && tempblackssum > 0)
{
for(int e=0; e<n; e++)
{
//Somehow divide the previously found area by two and check again if there are black and white squares in this area
}
for(int r=0; r<m; r++)
{
//Somehow divide the previously found area by two and check again if there are black and white squares in this area
}
}
}
}
}}
return 0;
}
I strongly recommend recursion for this. In fact, Dynamic Programming (DP) would also be very useful, especially for larger bars. Recursion first ...
Recursion
Your recursive routine takes a 2-D array of characters (b and w). It returns the number of ways this can be broken.
First, the base cases: (1) if it's possible to break the given bar into a single piece (see my comment above, asking for clarification), return 1; (2) if the array is all one colour, return 1. For each of these, there's only one way for the bar to end up -- the way it was passed in.
Now, for the more complex case, when the bar can still be broken:
total_ways = 0
for each non-edge position in each dimension:
break the bar at that spot; form the two smaller bars, A and B.
count the ways to break each smaller bar: count(A) and count(B)
total_ways += count(A) * count(B)
return total_ways
Is that clear enough for the general approach? You still have plenty of coding to do, but using recursion allows you to think of only the two basic ideas when writing your function: (1) How do I know when I'm done, and what trivial result do I return then? (2) If I'm not done, how do I reduce the problem?
Dynamic Programming
This consists of keeping a record of situations you've already solved. The first thing you do in the routine is to check your "data base" to see whether you already know this case. If so, return the known result instead of recomputing. This includes the overhead of developing and implementing said data base, probably a look-up list (dictionary) of string arrays and integer results, such as ["bwb", "wbw"] => 5.

Sum of values at common indexes in all subsets?

In a recent problem where i have to sum all values at common indexes in all possible subsets of size k in array of size n.
For eg: If
array ={1,2,3}
Its subsets (k=2) will be (x [i] , x [j]) where i < j
1 2
1 3
2 3
Sum:4,8
Firstly I have used recursion (same that of generating all subsets)
int sum_index[k]={0};
void sub_set(int array[],int n,int k,int temp[],int q=0,int r=0)
{
if(q==k)
{
for(int i=0;i<k;i++)
sum_index[i]+=temp[i];
}
else
{
for(int i=r;i<n;i++)
{
temp[q]=array[i];
sub_set(value,n,k,temp,q+1,i+1);
}
}
}
Problem is its taking too much time then expected .
Then i modified it to...
void sub_set(int array[],int n,int k,int temp[],int q=0,int r=0)
{
if(q==k)
{
return;
}
else
{
for(int i=r;i<n;i++)
{
temp[q]=array[i];
sum_index[q]+=temp[q]; //or sum_index[q]+=s[i];
sub_set(value,n,k,temp,q+1,i+1);
}
}
}
Still taking too much time!!
Is there any other approach to this problem?? Or any other modification i needed that i am unaware of??
Instead of iterating through the possible sub-sets, think of it a combinatorics problem.
To use your example of k=2 and {1,2,3}, let's just look at the first value of the result. It has two 1's and one 2. The two 1's correspond to the number one element sets that can be made from {2, 3} and the one 2 corresponds to the number of one element sets that can be made from {3}. A similar arrangement exists for the one 2 and two 3's in the second element of the result and looking at the subsets of the elements that appear before the element being considered.
Things get a bit more complicated when k>2 because then you will have to look for the number of combinations of elements before and after the element being considered, but the basic premise still works. Multiply the number of possible subsets before times the number of subsets afterwards and that will tell you how many times each element contributes to the result.
A solution in O(n^2) instead of O(n!):
First a tiny (:)) bit of explanation, then some code:
I´m going to assume here that your array is sorted (if not, use std::sort first). Additionally, I´m going to work with the array values 1,2,3,4... here, if you array consists arbitrary values (like 2 8 17), you´ll have to think of it as the indices (ie. 1=>2, 2=>8 etc.)
Definition: (x choose y) means the binomial coefficient, how it is calculated is in the link too. If you have an array size a and some k for the subset size, (a choose k) is the number of permutations, eg. 3 for your example: (1,2), (1,3) and (2,3).
You want the sum for each column if you write the permutations under each other, this would be easy if you knew for each column how many times each array element occurs, ie. how many 1´s, 2´s and 3´s for the first, and how many for second column (with k=2).
Here a bigger example to explain: (1,2,3,4,5) and all possible k´s (each in one block):
1
2
3
4
5
12
13
14
15
23
24
25
34
35
45
123
124
125
134
135
145
234
235
245
345
... (didn´t write k=4)
12345
Let´s introduce column indices, 0<=c<k, ie. c=0 means the first column, c=1 the second and so on; and the array size s=5.
So, looking eg. at the k=3-block, you´ll notice that the lines beginning with 1 (column c=0) have all permutations of the values (2,3,4,5) for k=2, more generally a value x in column c has all permutations for values x+1 to s after it. The values from from x+1 to s are s-x different values, and after column c there are k-c-1 more columns. So, for a value x, you can calculate ((s-x) choose (k-c-1)).
Additionally, the first column has only the values 1,2,3, the last two numbers are not here because after this column there are two more columns.
If you do this for the first column, it works well. Eg. with value 1 in the first column of k=3 above:
count(x) = ((s-x) choose (k-c-1)) = (4 choose 2) = 6
and indeed there are six 1 there. Calculate this count for every array value, multiply x*count(x), and sum it up for every x, that´s the result for the first column.
The other columns are a tiny bit harder, because there can be multiple "permutation blocks" of the same number. To start with, the step above needs a small adjustment: You need a muliplier array somewhere, one multiplier for each array value, and in the beginning each multiplier is 1. In the calculation x*count(x) above, take x*count(x)*muliplier(x) instead.
In the k=3-example, 1 in the first column can be followed by 2,3,4, 2 can be followed by 3,4, and 3 by 4. So the 3-based permutations of the second column need to be counted twice, and the 4-based even three times; more generally so many times like there are smaller values in the previos colums. Multiply that to the current multiplier.
...
Some code:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
// factorial (x!)
unsigned long long fact(unsigned char x)
{
unsigned long long res = 1;
while(x)
{
res *= x;
x--;
}
return res;
}
//binomial coefficient (n choose k)
unsigned long long binom(unsigned char n, unsigned char k)
{
if(!n || !k) return 1;
return (fact(n) / fact(k)) / fact(n-k);
}
//just for convenience
template<class T> void printvector(std::vector<T> data)
{
for(auto l : data) cout << l << " ";
cout << endl;
}
std::vector<unsigned long long> calculate(std::vector<int> data, int k)
{
std::vector<unsigned long long> res(k, 0); //result data
std::vector<unsigned long long> multiplier(data.size(), 1);
if(k < 1 || k > 255 || data.size() < 1) return res; //invalid stuff
std::sort(data.begin(), data.end()); //as described
for(int column = 0; column < k; column++) //each column separately
{
//count what to multiply to the multiplier array later
std::vector<unsigned long long> newmultiplier(data.size(), 0);
//for each array element in this column
for(int x = column; x <= (data.size() + column - k); x++)
{
//core calculation
res[column] += data[x] * multiplier[x] * binom(data.size() - x - 1, k - column - 1);
//counting the new multiplier factor
for(int helper = x + 1; helper < data.size(); helper++)
newmultiplier[helper]++;
}
//calculating new multiplier
for(int x = 0; x < data.size(); x++)
{
if(newmultiplier[x])
multiplier[x] *= newmultiplier[x];
}
}
return res;
}
int main() {
printvector(calculate({1,2,3}, 2)); //output 4 8
return 0;
}
std::next_permutation may help:
std::vector<int> sub_set(const std::vector<int>& a, int k)
{
std::vector<int> res(k, 0);
std::vector<bool> p(a.size() - k, false);
p.resize(a.size(), true);
do
{
int index = 0;
for (std::size_t i = 0; i != p.size(); ++i) {
if (p[i]) {
res[index++] += a[i];
}
}
} while (std::next_permutation(p.begin(), p.end()));
return res;
}
Live Demo

Segmentation fault while doing DFS on a coloured graph

Here is my Code:
#include <bits/stdc++.h>
using namespace std;
#define limt 101
//edge stores the edges for each node
//since it is defined outside main, i don't think it is the cause for
//segmentation fault
vector<int> edge[limt][limt];
int vist[limt], tgt;
//dfs call for a node numbered <i>u</i>
//and for only the edges colored <i>c</i>
int dfs(int u, int c)
{
if (u == tgt) return 1;
vist[u] = 1;
for (int i = 0; i < edge[u][c].size(); ++i) {
if (dfs(edge[u][c][i], c)) return 1;
}
vist[u] = 0;
return 0;
}
int main()
{
//n : number of nodes
//m: number of edges
//c: color of edge
int n, m;
int u, v, c;
cin >> n >> m;
for (int i = 0; i < m; ++i) {
cin >> u >> v >> c;
edge[u][c].push_back(v);
edge[v][c].push_back(u);
}
//q: number of queries/test-cases
int q, x, y;
cin >> q;
while (q--) {
cin >> x >> y;
memset(vist, 0, sizeof(vist));
int ans = 0;
vist[x] = 1;
tgt = y;
//program crashes for second test-case after reaching here
//i - the color of edge
//j - all the edges from x of color i
for (int i = 0; i < limt; ++i) {
for (int j = 0; j < edge[x][i].size(); ++j) {
ans += dfs(edge[x][i][j], i);
}
}
vist[x] = 0;
cout << ans << endl;
}
return 0;
}
The input i am giving is:
4 5
1 2 1
1 2 2
2 3 1
2 3 3
2 4 3
3
1 2
3 4
1 4
Here q is the number of test cases, the first case runs fine and gives the output 2 but on the second case program crashes with segmentation fault. I don't know what is the bug in it. I am sure i am not causing any overflow as the declarations are outside main().
In the second case, the dfs function causes infinite recursion.
The first call is dfs(u=2, c=1); which calls dfs(u=1, c=1); which calls dfs(u=2, c=1); and so on ad nauseum.
If you run your code in a debugger you should be able to see what happened by outputting the stack trace at the point of the segmentation fault.
Here is a picture of the graph generated by your data (where the colours are 1=red, 2=green, 3=blue):
Your loop inside main() starts at 3 and follows Red to find 2, then calls dfs(2, red); . (This was already a bit strange as you could have just called dfs(3, red) to get the same result). But then the dfs function just follows the first Red edge it finds so it ends up shuttling back and forth between 2 and 1.
To avoid this case you will need to add a way for dfs to know not to revisit a node it already visited. In fact you keep track of vist already but do not check it in the dfs function.
I think that just adding if ( vist[u] ) return 0; to the start of that function will fix this problem for this graph. However I think you should reset all of vist to 0 for each colour, not just for each testcase. For example in this graph if there were a blue edge from 2 to 4 but not from 3 to 4, the search would never find it because 2 was already marked visited during the red search.

C++: Return row & column of a given number in a matrix, function

novice C++ programmer here (using Visual Studio 2013).
I'd like to write a function where I can insert a number, and it will check if that number has a zero directly above, below or beside it, and then return the position of the zero.
For example, if I want to check the surroundings of number 2 which is at (1, 1), I want it to return (if there is any) the position of 0 which is at (1, 2). How would I go about doing this? Should I use matrix field instead (int a[][] e.g.)?
The function will be used to determine if the number, say 2, is able to swap places with the another number (zero in my case), and it can only do so if the zero is directly above, below or beside it.
3 5 6 8
9 2 0 7
1 8 9 3
1 3 5 7
This is my code so far, it only creates a vector matrix (sorry if I'm using the incorrect terms), randomizes a number between 1 - 15 and places it at a (row, col), and then replaces a number in a chosen (row, col) with a zero with the function set_zero.
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <vector>
using namespace std;
void set_zero(int row, int column, vector<vector<int>>& v){
v[row][column] = 0;
}
void scan_zero(vector<vector<int>>& v){
}
int _tmain(int argc, _TCHAR* argv[])
{
const int x = 4;
vector<vector<int>> v(x, vector<int>(x));
for (int i = 0; i < x; i++){
for (int j = 0; j < x; j++){
v[i][j] = rand() % 15 + 1;
}
}
set_zero(1, 2, v);
for (int i = 0; i < x; i++){
for (int j = 0; j < x; j++){
cout << setw(3) << v[i][j] << " ";
}
cout << endl;
}
}
I've tried searching the web for something similiar but I haven't found it, I'm sure it's out there but I just don't know how to properly formulate the search question.
Yeah, let's try using a 2d array (which simulates a matrix, int a[][] is referred to a 2d matrix).
Following your example: You want to check if the adjacent entries are zero. Let's use your example of (1,1) being 2.
A series of if statements could be your solution.
Let matrix be an integer 2d matrix of some size.
if matrix[1][2] equals 0 then
return positionRight
if matrix[1][0] equals 0 then
return positionLeft
if matrix[0][1] equals 0 then
return positionUp
if matrix[2][1] equals 0 then
return positionDown
Since your you're only checking the indexes directly adjacent, 4 if statements isn't that bad of an idea to inspect for an adjacent zero.
I think this might be a solution, it feels a bit primitive though.
Because I couldn't figure out how to return two values I just made two functions, one returning the position of the row, one of the column for the zero.
I did also run into the problem when it extends out of bounds of the matrix, so because I had a 4x4 matrix, i instead made it 6x6 and surrounded it with a frame of -1s.
int scan_zero_r(int r, int c, vector<vector<int>>& v){
int l = r + 1, k = r - 1;
if (v[l][c] == 0)
return l;
if (v[k][c] == 0)
return k;
else
return r;
}
int scan_zero_c(int r, int c, vector<vector<int>>& v){
int l = c + 1, k = c - 1;
if (v[r][l] == 0)
return l;
if (v[r][k] == 0)
return k;
else
return c;
}