#include #include #include #include #include using namespace std; struct OperationParam { int type; int rowOrColId; int leftOrRightShift; int shiftCount; OperationParam(int _type, int _rowOrColId, int _leftOrRightShift, int _shiftCount) : type(_type), rowOrColId(_rowOrColId), leftOrRightShift(_leftOrRightShift), shiftCount(_shiftCount) {} }; class MatrixOp { public: MatrixOp(); MatrixOp(int dimension, int operations); ~MatrixOp(); void SetCellInitalMatrix(int row, int col, int value); void SetCellFinalMatrix(int row, int col, int value); void AddOperation(OperationParam m_param); void PreCalculation(); int CountValidSolution(); private: vector< vector< int > > initialMatrix; vector< vector< int > > finalMatrix; vector< vector< vector< int > > > intermediateConfiguration; vector< vector< vector< int > > > forward_intermediateConfiguration; vector< OperationParam > m_operations; void SolveReverse(int index); void SolveForward(int index); void RowLeftShift(vector< vector < int > >& m_intermediateConfiguration, int rowId); void RowRightShift(vector< vector < int > >& m_intermediateConfiguration, int rowId); void ColLeftShift(vector< vector < int > >& m_intermediateConfiguration, int colId); void ColRightShift(vector< vector < int > >& m_intermediateConfiguration, int colId); void CopyMatrix(vector< vector< int > > m_source, vector< vector< int > >& m_destination); bool IsMatrixSame(vector< vector< int > > m_A, vector< vector< int > > m_B); int matrixDimension; int operationCount; }; MatrixOp::MatrixOp() { } MatrixOp::MatrixOp(int dimension, int operations) { matrixDimension = dimension; operationCount = operations; initialMatrix.resize(matrixDimension); finalMatrix.resize(matrixDimension); intermediateConfiguration.resize(operations); forward_intermediateConfiguration.resize(operations); for(int idx = 0; idx < operations; ++idx) { intermediateConfiguration[idx].resize(dimension); forward_intermediateConfiguration[idx].resize(dimension); for(int row = 0; row < 3; ++row) { intermediateConfiguration[idx][row].resize(dimension); forward_intermediateConfiguration[idx][row].resize(dimension); } } for(int row = 0; row < matrixDimension; ++row) { initialMatrix[row].resize(matrixDimension); finalMatrix[row].resize(matrixDimension); } } MatrixOp::~MatrixOp() { for(int row = 0; row < matrixDimension; ++row) { initialMatrix[row].clear(); finalMatrix[row].clear(); } for(int idx = 0; idx < operationCount; ++idx) { for(int row = 0; row < matrixDimension; ++row) { intermediateConfiguration[idx][row].clear(); forward_intermediateConfiguration[idx][row].clear(); } intermediateConfiguration[idx].clear(); forward_intermediateConfiguration[idx].clear(); } intermediateConfiguration.clear(); forward_intermediateConfiguration.clear(); initialMatrix.clear(); finalMatrix.clear(); m_operations.clear(); } void MatrixOp::SetCellInitalMatrix(int row, int col, int value) { initialMatrix[row][col] = value; } void MatrixOp::SetCellFinalMatrix(int row, int col, int value) { finalMatrix[row][col] = value; } void MatrixOp::AddOperation(OperationParam m_param) { m_operations.push_back(m_param); } void MatrixOp::RowLeftShift(vector >& m_intermediateConfiguration, int rowId) { int element = m_intermediateConfiguration[rowId][0]; m_intermediateConfiguration[rowId][0] = m_intermediateConfiguration[rowId][1]; m_intermediateConfiguration[rowId][1] = m_intermediateConfiguration[rowId][2]; m_intermediateConfiguration[rowId][2] = element; } void MatrixOp::RowRightShift(vector > &m_intermediateConfiguration, int rowId) { int element = m_intermediateConfiguration[rowId][2]; m_intermediateConfiguration[rowId][2] = m_intermediateConfiguration[rowId][1]; m_intermediateConfiguration[rowId][1] = m_intermediateConfiguration[rowId][0]; m_intermediateConfiguration[rowId][0] = element; } void MatrixOp::ColLeftShift(vector > &m_intermediateConfiguration, int colId) { int element = m_intermediateConfiguration[0][colId]; m_intermediateConfiguration[0][colId] = m_intermediateConfiguration[1][colId]; m_intermediateConfiguration[1][colId] = m_intermediateConfiguration[2][colId]; m_intermediateConfiguration[2][colId] = element; } void MatrixOp::ColRightShift(vector > &m_intermediateConfiguration, int colId) { int element = m_intermediateConfiguration[2][colId]; m_intermediateConfiguration[2][colId] = m_intermediateConfiguration[1][colId]; m_intermediateConfiguration[1][colId] = m_intermediateConfiguration[0][colId]; m_intermediateConfiguration[0][colId] = element; } void MatrixOp::CopyMatrix(vector > m_source, vector >& m_destination) { for(int row = 0; row < matrixDimension; ++row) { for(int col = 0; col < matrixDimension; ++col) { m_destination[row][col] = m_source[row][col]; } } } bool MatrixOp::IsMatrixSame(vector > m_A, vector > m_B) { for(int row = 0; row < matrixDimension; ++row) { for(int col = 0; col < matrixDimension; ++col) { if(m_A[row][col] != m_B[row][col]) { return false; } } } return true; } void MatrixOp::SolveReverse(int index) { int rowId; int colId; int shiftDir; int shiftCount; if(index + 1 == operationCount) { this->CopyMatrix(finalMatrix, intermediateConfiguration[index]); } else { this->CopyMatrix(intermediateConfiguration[index + 1], intermediateConfiguration[index]); } if(m_operations[index].type == 1) { rowId = m_operations[index].rowOrColId - 1; shiftDir = m_operations[index].leftOrRightShift; shiftCount = m_operations[index].shiftCount; if(shiftDir == 1) shiftDir = 2; else shiftDir = 1; if(shiftDir == 1) { for(int count = 1; count <= shiftCount; ++count) { this->RowLeftShift(intermediateConfiguration[index], rowId); } } else { for(int count = 1; count <= shiftCount; ++count) { this->RowRightShift(intermediateConfiguration[index], rowId); } } } else { colId = m_operations[index].rowOrColId - 1; shiftDir = m_operations[index].leftOrRightShift; shiftCount = m_operations[index].shiftCount; if(shiftDir == 1) shiftDir = 2; else shiftDir = 1; if(shiftDir == 1) { for(int count = 1; count <= shiftCount; ++count) { this->ColLeftShift(intermediateConfiguration[index], colId); } } else { for(int count = 1; count <= shiftCount; ++count) { this->ColRightShift(intermediateConfiguration[index], colId); } } } } void MatrixOp::SolveForward(int index) { int rowId; int colId; int shiftDir; int shiftCount; if(index == 0) { this->CopyMatrix(initialMatrix, forward_intermediateConfiguration[index]); } else { this->CopyMatrix(forward_intermediateConfiguration[index - 1], forward_intermediateConfiguration[index]); } if(m_operations[index].type == 1) { rowId = m_operations[index].rowOrColId - 1; shiftDir = m_operations[index].leftOrRightShift; shiftCount = m_operations[index].shiftCount; if(shiftDir == 1) { for(int count = 1; count <= shiftCount; ++count) { this->RowLeftShift(forward_intermediateConfiguration[index], rowId); } } else { for(int count = 1; count <= shiftCount; ++count) { this->RowRightShift(forward_intermediateConfiguration[index], rowId); } } } else { colId = m_operations[index].rowOrColId - 1; shiftDir = m_operations[index].leftOrRightShift; shiftCount = m_operations[index].shiftCount; if(shiftDir == 1) { for(int count = 1; count <= shiftCount; ++count) { this->ColLeftShift(forward_intermediateConfiguration[index], colId); } } else { for(int count = 1; count <= shiftCount; ++count) { this->ColRightShift(forward_intermediateConfiguration[index], colId); } } } } void MatrixOp::PreCalculation() { for(int op = operationCount - 1; op >= 0; --op) { this->SolveReverse(op); } for(int op = 0; op < operationCount; ++op) { this->SolveForward(op); } } int MatrixOp::CountValidSolution() { int fResult = 0; vector< vector< int > > currConfig; currConfig.resize(matrixDimension); for(int row = 0; row < matrixDimension; ++row) { currConfig[row].resize(matrixDimension); } for(int op = 0; op <= operationCount; ++op) { // Row/Col Operation for(int rowOrCol = 0; rowOrCol < matrixDimension; ++rowOrCol) { for(int operationType = 1; operationType <= 2; ++operationType) { if(op == 0) this->CopyMatrix(initialMatrix, currConfig); else { this->CopyMatrix(forward_intermediateConfiguration[op - 1], currConfig); } for(int shift = 1; shift <= 2; ++shift) { if(operationType == 1) { this->RowLeftShift(currConfig, rowOrCol); } else { this->RowRightShift(currConfig, rowOrCol); } if(op == operationCount) { if(IsMatrixSame(currConfig, finalMatrix)) { fResult += 1; } } else { if(IsMatrixSame(currConfig, intermediateConfiguration[op])) { fResult += 1; } } } if(op == 0) this->CopyMatrix(initialMatrix, currConfig); else { this->CopyMatrix(forward_intermediateConfiguration[op - 1], currConfig); } for(int shift = 1; shift <= 2; ++shift) { if(operationType == 1) { this->ColLeftShift(currConfig, rowOrCol); } else { this->ColRightShift(currConfig, rowOrCol); } if(op == operationCount) { if(IsMatrixSame(currConfig, finalMatrix)) { fResult += 1; } } else { if(IsMatrixSame(currConfig, intermediateConfiguration[op])) { fResult += 1; } } } } } } return fResult; } int main() { cin.sync_with_stdio(false); int type; int rowOrColId; int leftOrRightShift; int shiftCount; int operations; int dimension = 3; int value; MatrixOp *m_matrix; cin >> operations; m_matrix = new MatrixOp(dimension, operations - 1); for(int op = 1; op < operations; ++op) { cin >> type >> rowOrColId >> leftOrRightShift >> shiftCount; m_matrix->AddOperation( OperationParam(type, rowOrColId, leftOrRightShift, shiftCount)); } // Initial Matrix for(int row = 0; row < dimension; ++row) { for(int col = 0; col < dimension; ++col) { cin >> value; m_matrix->SetCellInitalMatrix(row, col, value); } } // Final Matrix for(int row = 0; row < dimension; ++row) { for(int col = 0; col < dimension; ++col) { cin >> value; m_matrix->SetCellFinalMatrix(row, col, value); } } m_matrix->PreCalculation(); int finalAns = m_matrix->CountValidSolution(); cout << finalAns << endl; m_matrix->~MatrixOp(); }