现在的位置: 首页 > 综合 > 正文

包围的区域

2013年03月05日 ⁄ 综合 ⁄ 共 4245字 ⁄ 字号 评论关闭

问题来源: 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

我也写复杂了...

 

抱歉!评论已关闭.