遞歸回溯法實戰(一)——(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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章