https://www.acmicpc.net/problem/12100

Source

	void _DFS(const vvi &map, const int numMoves, const Dir_e dir) {
		vvi movedMap(map);
#if 1
        _MoveWithQ(dir, movedMap);
#else
        _Move(dir, movedMap);
#endif // 0

		if (numMoves == MAX_MOVES)
        {
			const int biggest = GetBiggest(movedMap);
			if (biggest > m_maxVal) {
				m_maxVal = biggest;
			}
			return;
		}

		FOR(nextDir, eDIR_LEN) {
			_DFS(movedMap, numMoves + 1, (Dir_e)nextDir);
		}
	}

	int _MoveWithQ(const Dir_e dir, vvi &mapOut) {
		int numMerges = 0;
		switch (dir)
		{
		case eR:
			FOR(row, m_mapSizeN) {
				qi qiVals;
				FOR_DEC(col, 0, m_mapSizeN) {
					const int val = mapOut[row][col];
					if (val > 0) {
						mapOut[row][col] = 0;
						qiVals.push(val);
					}
				}

				FOR_DEC(col, 0, m_mapSizeN) {
					_FillCell(row, col,
							  mapOut, qiVals, numMerges);
				}
			}
			break;
		case eD:
			FOR(col, m_mapSizeN) {
				qi qiVals;
				FOR_DEC(row, 0, m_mapSizeN) {
					const int val = mapOut[row][col];
					if (val > 0) {
						mapOut[row][col] = 0;
						qiVals.push(val);
					}
				}

				FOR_DEC(row, 0, m_mapSizeN) {
					_FillCell(row, col,
							  mapOut, qiVals, numMerges);
				}
			}
			break;
		case eL:
			FOR(row, m_mapSizeN) {
				qi qiVals;
				FOR_INC(col, 0, m_mapSizeN) {
					const int val = mapOut[row][col];
					if (val > 0) {
						mapOut[row][col] = 0;
						qiVals.push(val);
					}
				}

				FOR_INC(col, 0, m_mapSizeN) {
					_FillCell(row, col,
							  mapOut, qiVals, numMerges);
				}
			}
			break;
		case eU:
			FOR(col, m_mapSizeN) {
				qi qiVals;
				FOR_INC(row, 0, m_mapSizeN) {
					const int val = mapOut[row][col];
					if (val > 0) {
						mapOut[row][col] = 0;
						qiVals.push(val);
					}
				}

				FOR_INC(row, 0, m_mapSizeN) {
					_FillCell(row, col,
							  mapOut, qiVals, numMerges);
				}
			}
			break;
		default:
			P_IFNOT(dir < eDIR_LEN, dir);
			break;
		}

		return numMerges;
	}

	void _FillCell(const int row, const int col,
				   vvi &mapOut, qi &qiValsOut, int &numMergesOut) {
		int pivotVal = -1;

		// A. visit next

		while (!qiValsOut.empty()) {
			const int val = qiValsOut.front();

			// C. check to be merged

			if (val == pivotVal) {
				mapOut[row][col] = pivotVal * 2;
				pivotVal = -1;
				numMergesOut++;
				qiValsOut.pop();
				break;
			}
			else {
				if (pivotVal != -1) {
					pivotVal = -1;
					break;
				}
			}

			// D. set pivot

			pivotVal = val;
			mapOut[row][col] = pivotVal;
			qiValsOut.pop();
		}
	}

	int _Move(const Dir_e dir, vvi &mapOut) {
		int numMerges = 0;
		switch (dir)
		{
		case eR:
			FOR(row, m_mapSizeN) {
				int pivotVal = 0;
				int pivotCol = 0;
				int emptyCellCol = 0;
				FOR_DEC(col, 0, m_mapSizeN) {
					// A. visit next

					const int val = mapOut[row][col];
					if (val > 0) {
						if (pivotVal != 0) {
							// C. check to be merged

							if (pivotVal == val) {
								mapOut[row][pivotCol] = pivotVal * 2;
								pivotVal = 0;
								mapOut[row][col] = 0;
								numMerges++;

								// G. set empty cell

								if (emptyCellCol == 0) {
									emptyCellCol = col;
								}
								continue;
							}
						}

						// D. set pivot

						pivotVal = val;
						if (emptyCellCol > 0) {
							pivotCol = emptyCellCol;

							// E. move pivot value into empty cell

							mapOut[row][emptyCellCol] = pivotVal;
							mapOut[row][col] = 0;

							// F. set next empty cell

							if (emptyCellCol > col) {
								--emptyCellCol;
							}
						}
						else {
							pivotCol = col;
						}
					}
					else {
						// B. set empty cell

						if (emptyCellCol == 0) {
							emptyCellCol = col;
						}
					}
				}
			}
			break;
		case eD:
			FOR(col, m_mapSizeN) {
				int pivotVal = 0;
				int pivotRow = 0;
				int emptyCellRow = 0;
				FOR_DEC(row, 0, m_mapSizeN) {
					// A. visit next

					const int val = mapOut[row][col];
					if (val > 0) {
						if (pivotVal != 0) {
							// C. check to be merged

							if (pivotVal == val) {
								mapOut[pivotRow][col] = pivotVal * 2;
								pivotVal = 0;
								mapOut[row][col] = 0;
								numMerges++;

								// G. set empty cell

								if (emptyCellRow == 0) {
									emptyCellRow = row;
								}
								continue;
							}
						}

						// D. set pivot

						pivotVal = val;
						if (emptyCellRow > 0) {
							pivotRow = emptyCellRow;

							// E. move pivot value into empty cell

							mapOut[emptyCellRow][col] = pivotVal;
							mapOut[row][col] = 0;

							// F. set next empty cell

							if (emptyCellRow > row) {
								--emptyCellRow;
							}
						}
						else {
							pivotRow = row;
						}
					}
					else {
						// B. set empty cell

						if (emptyCellRow == 0) {
							emptyCellRow = row;
						}
					}
				}
			}
			break;
		case eL:
			FOR(row, m_mapSizeN) {
				int pivotVal = 0;
				int pivotCol = 0;
				int emptyCellCol = m_mapSizeN;
				FOR_INC(col, 0, m_mapSizeN) {
					// A. visit next

					const int val = mapOut[row][col];
					if (val > 0) {
						if (pivotVal != 0) {
							// C. check to be merged

							if (pivotVal == val) {
								mapOut[row][pivotCol] = pivotVal * 2;
								pivotVal = 0;
								mapOut[row][col] = 0;
								numMerges++;

								// G. set empty cell

								if (emptyCellCol == m_mapSizeN) {
									emptyCellCol = col;
								}
								continue;
							}
						}

						// D. set pivot

						pivotVal = val;
						if (emptyCellCol < m_mapSizeN) {
							pivotCol = emptyCellCol;

							// E. move pivot value into empty cell

							mapOut[row][emptyCellCol] = pivotVal;
							mapOut[row][col] = 0;

							// F. set next empty cell

							if (emptyCellCol < col) {
								++emptyCellCol;
							}
						}
						else {
							pivotCol = col;
						}
					}
					else {
						// B. set empty cell

						if (emptyCellCol == m_mapSizeN) {
							emptyCellCol = col;
						}
					}
				}
			}
			break;
		case eU:
			FOR(col, m_mapSizeN) {
				int pivotVal = 0;
				int pivotRow = 0;
				int emptyCellRow = m_mapSizeN;
				FOR_INC(row, 0, m_mapSizeN) {
					// A. visit next

					const int val = mapOut[row][col];
					if (val > 0) {
						if (pivotVal != 0) {
							// C. check to be merged

							if (pivotVal == val) {
								mapOut[pivotRow][col] = pivotVal * 2;
								pivotVal = 0;
								mapOut[row][col] = 0;
								numMerges++;

								// G. set empty cell

								if (emptyCellRow == m_mapSizeN) {
									emptyCellRow = row;
								}
								continue;
							}
						}

						// D. set pivot

						pivotVal = val;
						if (emptyCellRow < m_mapSizeN) {
							pivotRow = emptyCellRow;

							// E. move pivot value into empty cell

							mapOut[emptyCellRow][col] = pivotVal;
							mapOut[row][col] = 0;

							// F. set next empty cell

							if (emptyCellRow < row) {
								++emptyCellRow;
							}
						}
						else {
							pivotRow = row;
						}
					}
					else {
						// B. set empty cell

						if (emptyCellRow == m_mapSizeN) {
							emptyCellRow = row;
						}
					}
				}
			}
			break;
		default:
			P_IFNOT(dir < eDIR_LEN, dir);
			break;
		}

		return numMerges;
	}

GitHub

Game2048