问题来源: http://www.blogjava.net/sandy/archive/2013/04/15/397875.html
问题: 给定一个2D的棋盘, 含有'X'和'O', 找到所有被'X'包围的'O', 然后把该区域的'O'都变成'X'
#include <cstdio>
#include <fstream>
enum FLAG
{
X = 'X',
O = 'O'
};
enum STATE
{
DANGER,
SAFETY,
UNKNOWN
};
class Game
{
public:
Game();
~Game();
public:
bool init(const char * file);
void solve_way_1();
void roll_back();
void solve_way_2();
void show(bool before);
private:
bool create_status(int row_num, int col_num);
void clear_status();
bool load_status(std::ifstream & ifs);
STATE solve_one_way_1(int row, int col);
void solve_one_way_2(int row, int col);
private:
Game(const Game &);
Game & operator = (const Game &);
private:
struct STATUS
{
FLAG bef_flag;
FLAG aft_flag;
STATE state;
};
private:
int m_row;
int m_col;
int m_row_max;
int m_col_max;
STATUS ** m_status;
};
Game::Game()
: m_status(NULL)
, m_row(0)
, m_col(0)
, m_row_max(0)
, m_col_max(0)
{
}
Game::~Game()
{
clear_status();
}
bool Game::init(const char * file)
{
if (NULL == file)
{
return(false);
}
std::ifstream ifs(file);
if (!ifs.is_open())
{
return(false);
}
int row_num = 0;
int col_num = 0;
ifs >> row_num;
ifs >> col_num;
if (0 >= row_num || 0 >= col_num)
{
return(false);
}
if (row_num <= m_row_max && col_num <= m_col_max)
{
m_row = row_num;
m_col = col_num;
}
else
{
clear_status();
if (!create_status(row_num, col_num))
{
return(false);
}
}
return(load_status(ifs));
}
bool Game::create_status(int row_num, int col_num)
{
typedef STATUS * PSTATUS;
m_status = new PSTATUS[row_num];
if (NULL == m_status)
{
return(false);
}
m_col = col_num;
m_col_max = col_num;
for (m_row = 0; m_row < row_num; ++m_row)
{
m_status[m_row] = new STATUS[col_num];
if (NULL == m_status[m_row])
{
break;
}
}
m_row_max = m_row;
return(m_row == row_num);
}
void Game::clear_status()
{
for (int row = 0; row < m_row_max; ++row)
{
delete [] m_status[row];
}
delete [] m_status;
m_row = 0;
m_col = 0;
m_row_max = 0;
m_col_max = 0;
}
bool Game::load_status(std::ifstream & ifs)
{
for (int row = 0; row < m_row; ++row)
{
for (int col = 0; col < m_col; ++col)
{
STATUS & status = m_status[row][col];
char flag = '\0';
ifs >> flag;
if (X == flag)
{
status.bef_flag = X;
status.aft_flag = X;
status.state = DANGER;
}
else if (O == flag)
{
status.bef_flag = O;
status.aft_flag = O;
status.state = UNKNOWN;
}
else
{
return(false);
}
}
}
return(ifs.good());
}
STATE Game::solve_one_way_1(int row, int col)
{
STATE & state = m_status[row][col].state;
if (UNKNOWN != state)
{
return(state);
}
FLAG & flag = m_status[row][col].aft_flag;
if (0 == row || m_row - 1 == row ||
0 == col || m_col - 1 == col ||
SAFETY == m_status[row - 1][col].state ||
SAFETY == m_status[row][col - 1].state ||
SAFETY == solve_one_way_1(row, col + 1) ||
SAFETY == solve_one_way_1(row + 1, col))
{
state = SAFETY;
flag = O;
}
else
{
state = DANGER;
flag = X;
}
return(state);
}
void Game::solve_way_1()
{
for (int row = 0; row < m_row; ++row)
{
for (int col = 0; col < m_col; ++col)
{
solve_one_way_1(row, col);
}
}
}
void Game::roll_back()
{
for (int row = 0; row < m_row; ++row)
{
for (int col = 0; col < m_col; ++col)
{
STATUS & status = m_status[row][col];
if (O == status.bef_flag)
{
status.aft_flag = O;
status.state = UNKNOWN;
}
}
}
}
void Game::solve_one_way_2(int row, int col)
{
if (0 > row || 0 > col || row >= m_row || col >= m_col)
{
return;
}
if (X == m_status[row][col].bef_flag ||
SAFETY == m_status[row][col].state)
{
return;
}
m_status[row][col].state = SAFETY;
solve_one_way_2(row - 1, col);
solve_one_way_2(row, col - 1);
solve_one_way_2(row + 1, col);
solve_one_way_2(row, col + 1);
}
void Game::solve_way_2()
{
for (int col = 0; col < m_col; ++col)
{
if (O == m_status[0][col].bef_flag)
{
m_status[0][col].state = SAFETY;
solve_one_way_2(1, col);
}
if (O == m_status[m_row - 1][col].bef_flag)
{
m_status[m_row - 1][col].state = SAFETY;
solve_one_way_2(m_row - 2, col);
}
}
for (int row = 1; row < m_row - 1; ++row)
{
if (O == m_status[row][0].bef_flag)
{
m_status[row][0].state = SAFETY;
solve_one_way_2(row, 1);
}
if (O == m_status[row][m_col - 1].bef_flag)
{
m_status[row][m_col - 1].state = SAFETY;
solve_one_way_2(row, m_col - 2);
}
}
for (int row = 0; row < m_row; ++row)
{
for (int col = 0; col < m_col; ++col)
{
if (UNKNOWN == m_status[row][col].state)
{
m_status[row][col].aft_flag = X;
}
}
}
}
void Game::show(bool before)
{
printf("--- %s ---\n", before ? "before" : "after ");
for (int row = 0; row < m_row; ++row)
{
for (int col = 0; col < m_col; ++col)
{
if (before)
{
printf("%c ", m_status[row][col].bef_flag);
}
else
{
printf("%c ", m_status[row][col].aft_flag);
}
}
printf("\n");
}
}
int main(int argc, char * argv[])
{
const char * file = "graph.txt";
Game game;
game.init(file);
printf("\n- way 1 -\n");
game.solve_way_1();
game.show(true);
game.show(false);
game.roll_back();
printf("\n- way 2 -\n");
game.solve_way_2();
game.show(true);
game.show(false);
return(0);
}
数据:
4
4
X X X X
X O O X
O X O X
O O X O
结果:
- way 1 -
--- before ---
X X X X
X O O X
O X O X
O O X O
--- after ---
X X X X
X X X X
O X X X
O O X O
- way 2 -
--- before ---
X X X X
X O O X
O X O X
O O X O
--- after ---
X X X X
X X X X
O X X X
O O X O
我也写复杂了...