递归回溯法实战(一)——(Red and Black)红黑砖迷阵(POJ1979)

问题模型

有一个矩形的房间里铺满正方形瓷砖。每块瓷砖涂成黑色或红色。一个人站在黑色的瓷砖上,从此出发,可以移动到四个相邻的瓷砖之一,但只能移动到黑色的瓷砖上。计算他通过重复上述移动所能经过的黑砖数。
示意图如下(画的有点丑(⊙﹏⊙)。)
这里写图片描述

输入

输入包含多个数据集。一个数据集开头行包括两个正整数W和H,W和H分别表示矩阵的列数和行数,切不超过20.
每个数据集有H行,其中每行包含W个字符。每个字符的含义如下所示。
‘R’——红砖
‘B’——黑砖
‘@’——人(每个数据集仅出现一次)
两个0表示结束

输出

这里写图片描述

分析

使用递归方法求解经过的瓷砖数。设n,m分别为矩形的行数和列数;sum为经过的瓷砖数;map为瓷砖图,其中map[i][j]为座标i , j的字符;visited为访问标志,visited[i][j]表示已经过座标(i,j);递归函数为search(i,j).其中:
状态:当前位置(i,j),递归前为出发位置。
边界条件:若当前座标在地图外(i<0 || i>=n || j<0 || j>=n)或不可通行(map[i][j] ==’R’),或已经访问过(visited[i][j] ==true),则回溯;否则将座标(i,j)设访问标志(visited[i][j] = true),经过的瓷砖数sum++,继续递归。
搜索范围:递归当前座标(i,j)的四个相邻点(i-1,j),(i+1,j),(i,j-1),(i,j+1).

编码

#include "stdafx.h"
#include <iostream>

using namespace std;

// R 红砖 B 黑砖 @人
const int MAX_ROW = 20, MAX_COLUMN = 20;

int sum, m, n;    //经过的瓷砖数    行数    列数
char map[MAX_ROW][MAX_COLUMN];
bool visited[MAX_ROW][MAX_COLUMN]; //记录访问标志的数组

//递归计算从(row,col)出发经过的瓷砖数
void search(int row, int col)
{
    //边界条件 座标在地图外,不可通行,已经访问过 则回溯
    if (row < 0 || row >= n || col < 0 || col >= n || map[row][col] == 'R' || visited[row][col])
    return;

    visited[row][col] = true; //设置当前座标的标志位
    ++sum; //经过的瓷砖数+1
    //递归遍历当前座标的四个相邻点
    search(row-1, col);
    search(row+1 , col);
    search(row , col-1);
    search(row, col+1);

}

int _tmain(int argc, _TCHAR* argv[]){
    cin >> m >> n;  //输入行数和列数

    while (m || n)
    {
        int row, col;
        for (int i = 0; i < n; i++)
        {
            cin>> map[i]; //输入当前行的数据集
            for (int j = 0; j < m; j++)
            {
                if (map[i][j] == '@')
                {
                    row = i;
                    col = j;
                }
            }
        }
        memset(visited,false,sizeof(visited));
        sum = 0;
        search(row, col);
        cout << sum << endl;
        cin >> m >> n;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章