程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> POJ 3009 Curling 2.0 {廣度優先搜索}

POJ 3009 Curling 2.0 {廣度優先搜索}

編輯:關於C++

原題

$On Planet MM-21, after their Olympic games this year, curling is getting popular. But the rules are somewhat different from ours. The game is played on an ice game board on which a square mesh is marked. They use only a single stone. The purpose of the game is to lead the stone from the start to the goal with the minimum number of moves.

Fig. 1 shows an example of a game board. Some squares may be occupied with blocks. There are two special squares namely the start and the goal, which are not occupied with blocks. (These two squares are distinct.) Once the stone begins to move, it will proceed until it hits a block. In order to bring the stone to the goal, you may have to stop the stone by hitting it against a block, and throw again.

The movement of the stone obeys the following rules:

At the beginning, the stone stands still at the start square.
The movements of the stone are restricted to x and y directions. Diagonal moves are prohibited.
When the stone stands still, you can make it moving by throwing it. You may throw it to any direction unless it is blocked immediately(Fig. 2(a)).
Once thrown, the stone keeps moving to the same direction until one of the following occurs:
The stone hits a block (Fig. 2(b), (c)).
The stone stops at the square next to the block it hit.
The block disappears.
The stone gets out of the board.
The game ends in failure.
The stone reaches the goal square.
The stone stops there and the game ends in success.
You cannot throw the stone more than 10 times in a game. If the stone does not reach the goal in 10 moves, the game ends in failure.

Under the rules, we would like to know whether the stone at the start can reach the goal and, if yes, the minimum number of moves required.

With the initial configuration shown in Fig. 1, 4 moves are required to bring the stone from the start to the goal. The route is shown in Fig. 3(a). Notice when the stone reaches the goal, the board configuration has changed as in Fig. 3(b).$

這裡寫圖片描述vc/yoaM8L3A+DQo8cD7H8sjnufuz9r3nwcujrNTyyqew3KO7yOe5+7n2tq/ByzEwtM7S1MnPzazR+cqnsNyhozwvcD4NCjxwPtb30qq+zcrH1eK49tLiy7yjrL+0v7TNvDO+zbauwcuhozwvcD4NCjxoMiBpZD0="思路">思路

這道題和之前有一道一樣,都是關於廣度優先搜索的,大家可以看看這個: POJ 1979 Red and Black(紅與黑)

這裡在二維數組中移動的方向和之前的定義一樣,圖示:

這裡寫圖片描述

首先需要輸入二維數組:

        for (int row = 0; row < H; ++row) {
            for (int col = 0; col < W; ++col) {
                cin >> room[row][col];
            }
        }

找到其中為2的即為起點,將當前的row和col復制相應的起始點(start),然後結束循環。

        // 為2的點為起始點
        for (int row = 0; row < H; ++row) {
            for (int col = 0; col < W; ++col) {
                if (room[row][col] == 2) {
                    sRow = row;
                    sCol = col;
                    break;
                }
            }
        }

因為此時已經不需要這個起始點了,將其重新設置為0,表示可以走。因為有完成的步數要求,所以需要加上一個判斷,超過10此輸出-1。其中的dfs函數為核心。

        room[sRow][sCol] = 0;
        minStep = 11;
        dfs(sRow, sCol, 0);
        if (minStep > 10) {
            minStep = -1;
        }
        // 輸出結果
        cout << minStep << endl;

在dfs函數的開頭需要做判斷。

    if (step >= 10 || step > minStep) {
        return;
    }

這裡的d有4個值,表示4個方向(上、右、下、左),之所以當前的(current)row和col都在for循環開始處,是因為如果走到不能走的地方可以立即返回並重新獲得當前(原本)的位置。

    for (int d = 0; d < 4; ++d) {
        int cRow = row;
        int cCol = col;
    }

無論如何都得讓點處於該范圍之中,其次是判斷這個點表示的意思。

while (cRow >= 0 && cRow < H && cCol >= 0 && cCol < W) {
    switch (room[cRow][cCol]) {
    }
}

0表示為空,所以繼續往該(d)方向走。

case 0: {
    cRow += direc[d][1];
    cCol += direc[d][0];
    break;
}

3表示為終點,如果step加上當前步驟比之前最小的步數還小,將其賦值給最小步數。

case 3: {
    if (step + 1 < minStep) {
        minStep = step + 1;
    }
    cRow = -1;
    break;
}

1表示為障礙,還原走多的這一步然後進行下一次遞歸,步數加1,位置還原。

case 1: {
    if (!(cRow - direc[d][1] == row && cCol - direc[d][0] == col)) {
        room[cRow][cCol] = 0;
        dfs(cRow - direc[d][1], cCol - direc[d][0], step + 1);
        room[cRow][cCol] = 1;
    }
    cRow = -1;
    break;
}

默認的情況。

default: {
    break;
}

代碼

#include       
using namespace std;

// 題目中給出的最大寬度和高度
#define MAX_W 20
#define MAX_H 20

// 待輸入的寬度和高度以及已走的步數
int W, H;
int step = 0;
int minStep;
int sRow, sCol;

// 待寫入的二維數組
int room[MAX_W][MAX_H];
// 順時針的可走方向
const int direc[4][2] = {
    { 0, -1 },
    { 1,0 },
    { 0, 1 },
    { -1 ,0 },
};

void dfs(const int& row, const int& col, int step) {
    if (step >= 10 || step > minStep) {
        return;
    }
    for (int d = 0; d < 4; ++d) {
        int cRow = row;
        int cCol = col;
        while (cRow >= 0 && cRow < H && cCol >= 0 && cCol < W) {
            switch (room[cRow][cCol]) {
            case 0: {
                cRow += direc[d][1];
                cCol += direc[d][0];
                break;
            }
            case 3: {
                if (step + 1 < minStep) {
                    minStep = step + 1;
                }
                cRow = -1;
                break;
            }
            case 1: {
                if (!(cRow - direc[d][1] == row && cCol - direc[d][0] == col)) {
                    room[cRow][cCol] = 0;
                    dfs(cRow - direc[d][1], cCol - direc[d][0], step + 1);
                    room[cRow][cCol] = 1;
                }
                cRow = -1;
                break;
            }
            default: {
                break;
            }
            }
        }
    }
}

int main()
{
    while (cin >> W >> H, W > 0) {
        // 輸入
        for (int row = 0; row < H; ++row) {
            for (int col = 0; col < W; ++col) {
                cin >> room[row][col];
            }
        }
        // 為2的點為起始點
        for (int row = 0; row < H; ++row) {
            for (int col = 0; col < W; ++col) {
                if (room[row][col] == 2) {
                    sRow = row;
                    sCol = col;
                    break;
                }
            }
        }
        room[sRow][sCol] = 0;
        minStep = 11;
        dfs(sRow, sCol, 0);
        if (minStep > 10) {
            minStep = -1;
        }
        // 輸出結果
        cout << minStep << endl;
    }
}

號外

求投票或轉發支持呀……希望我不要死得太慘了……

請點擊這裡:投票

投票從10號開始一直持續到20號,拜托各位了!


———————————————————當然你也可以直接點擊圖片啦

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved