suppose i got a matrix
0 1 0 0 2
0 0 0 4 0
5 0 2 1 3
4 4 5 0 0
0 3 2 0 2
Select a matching by choosing a set of zeros so that each row or column has only one selected. It means that i should have only one zero selected from each row and column!
i implemented several of my logics in mind but there comes a problem in every one! kindly help me! my project is badly stuck at this point just because of this stupid step!
i have to make a new matrix 2d in which the zeros from rows and columns should be selected in a way that they are unique!!
like in this case output should be
1 0 0 0 0
0 0 1 0 0
0 1 0 0 0
0 0 0 0 1
0 0 0 1 0
Perhaps a path finding AI algorithm such as a depth first search (look it up) would be helpful. Basically if you can define this class you can solve any problem:
class Node
{
private:
//anything you need
public:
vector<Node> getAllPossibleMoves();//in this case it would return all valid selections of 0s in your matrix
bool isVictory();//return true if this Node represents the goal
};
Hope this helps.
EDIT: Labdabeta beat me to it! I spent so much time on this one! Darn the luck!
I'd suggest a recursive function with a backtracking mechanism like a stack or a double-ended queue.
deque<yourClass> *myRecursiveFunction(vector< vector< yourClass > > *dataSet){
deque<yourClass> *dataSelected=new deque<yourClass>();
if(myRecursiveInnerFunction(currentDataSet, 0, dataSelected))
return dataSelected;
else
return NULL;
}
bool myRecursiveInnerFunction(vector< vector< yourClass > > *dataSet, int indexInDataSet, deque<yourClass> *dataSelected){
//Have we reached the end yet?
if((*dataSet)[indexInDataSet].size()>indexInDataSet){
//Nope! Still going.
//Let's loop through
for(int i=0;i<(*dataSet)[indexInDataSet].size();i++){
//Push next data piece onto the stack.
dataSelected->pushBack((*dataSet)[indexInDataSet][i]);
if(testValidHypothesis(dataSelected)){
//OK, this will work. So far so good.
if(myRecursiveInnerFunction(dataSet, indexInDataSet+1, dataSelected)){
//Hey! It worked! Ride the returns up back to the top!
return true;
}
}
//If we made it here, the data didn't work out. Oops.
//We remove the last piece.
dataSelected->pop_back();
//And we loop again.
}
//Looked through all possibilities for this set. An earlier piece of data must be wrong.
//Going back and trying again.
return false;
}
else{
//We've come to the end of the line. Everything checked out. We're done.
return true;
}
}
Using a recursive function as well. I just have one more bug (I think). I thought that function was getting to complex but maybe not.
Got to solve it, it's consuming me now.
The trick here is as you move through the matrix, you have to keep track of the zeros that tried before. What I did is as I walk through the matrix looking for zeros I check the candidate zero matrix element to see if the row that the zero is contained in is not in the current answer set.
I don't know if I explained it well enough so I'm going to post the code.
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <list>
using namespace std;
inline void printIt(vector<int> &m, int r,int c){
for (int i(0); i<r;i++){
for (int j(0); j<c;j++){
cout << m.at(i*c+j) << " ";
}
cout << endl;
}
}
void printAns(map<int,int> &ans,int r, int c){
cout << "Ans: " << endl;
for(int i(0);i<r;i++){
for(int j(0);j<c;j++){
if ( ans.find(i) != ans.end() && ans[i] == j)
cout << "1 ";
else
cout << "0 ";
}
cout << endl;
}
}
inline bool checkOK(int c, int r, map<int,list<int> > &a){
return (find(a[c].begin(),a[c].end(),r)==a[c].end());
}
inline void removeVal(int c, map<int,int> &ans){
map<int,int>::iterator pos(ans.begin());
for (;pos!=ans.end();pos++){
if ( pos->second == c ){
ans.erase(pos);
break;
}
}
}
bool findIt(int r, int c, int colSrch, vector<int> &m, map<int,int> &ans, map<int,list<int> > &dontUse){
bool ret(false),zero(false);
int i(0);
if ( ans.size() != r ) {
for ( i=0; i < r; i++){
zero |= !m.at(i*c+colSrch);
if ( ans.find(i) == ans.end() && !m.at(i*c+colSrch) && checkOK(colSrch,i,dontUse)){
ans[i] = colSrch;
dontUse[colSrch].push_back(i);
dontUse.erase(dontUse.find(colSrch+1),dontUse.end());
ret = findIt(r,c,colSrch+1,m,ans,dontUse);
break;
}
}
if ( zero ){
if (i==r && !ret) {
if ( colSrch-1 >= 0){
removeVal(colSrch-1,ans);
ret = findIt(r,c,colSrch-1,m,ans,dontUse);
}
}
}
}
else {
ret = true;
}
return ret;
}
int main(){
map<int,list<int> > dontUse;
map<int,int> ans;
vector<int> m;
int rows(5),cols(5);
m.push_back(0),m.push_back(1),m.push_back(0),m.push_back(0),m.push_back(2);
m.push_back(0),m.push_back(0),m.push_back(0),m.push_back(4),m.push_back(0);
m.push_back(5),m.push_back(0),m.push_back(2),m.push_back(1),m.push_back(3);
m.push_back(4),m.push_back(4),m.push_back(5),m.push_back(0),m.push_back(0);
m.push_back(0),m.push_back(3),m.push_back(2),m.push_back(0),m.push_back(2);
printIt(m,rows,cols);
if ( rows == cols )
if (findIt(rows,cols,0,m,ans,dontUse) )
printAns(ans,rows,cols);
else
cout << "No answer!" << endl;
else
cout << "Rows != Cols" << endl;
return 0;
}