蛇與梯子游戲 (BFS + priority_queue)

“蛇和梯子”是一個在NXN的(0<N<=20)的方格棋盤上進行的遊戲(如下圖)


方格從1到N的平方編號。除了第1號和最後編號的方格,其它的格子都有可能有蛇或梯子存在(蛇和梯子的數量及具體位置由輸入確定,它們的數量都在100之內並且蛇和梯子不能臨近放置,也就是在任何了放置兩者首尾的方格之間至少還有一個未放置任何東西的格子)。開始的時候玩家把他們的標誌物放在1號格子中。玩家輪流以扔骰子的方式移動他們的指示物。如果一個指示物到達了一條蛇的嘴部,則把它移回蛇的尾部。如果一個指示物到達了一個梯子的底部則將它移動到梯子的頂部。如果你是一個可以自由控制骰子的高手,現在請求出你至少需要扔幾次骰子才能到達標爲N^2的格子。(比如在上圖所示例一中,你的方案應該是走4步到達5並由梯子上升到16,再走4步到達20並由梯子上升到33,然後走3步。這樣,你一共需要扔3次骰子。而在例二中,你的方案應該是連扔4個6。

[輸入要求]

有多能測試數據,第一行輸入N,S,L,(0<N<=20, 0<S<=100, 0<L<=100)其中N表示方格行,S表示蛇的數目,L表示梯子數目,接下S行輸入蛇嘴部和尾部,L行輸入梯子的底部和頂部。

[輸出要求]

每組測試數據對應一個輸出,輸出能到達標爲N^2的格子最小的步數。


解析:這個遊戲是一個很經典的搜索問題,要求最快(最小拋骰子的次數),所以思路很明顯,廣搜,然後搜索效率的話,可以用優先隊列;然後圖,因爲是二維盤旋的,也沒有用座標表示,所以可以把它伸展爲一條長爲N*N的直線; 以下就是詳細的代碼實現及解析:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <set>
#include <queue>
#include <algorithm>
#define MAXN 450
#define RST(N)memset(N, 0, sizeof(N))
using namespace std;

typedef struct Node   //到達某位置時的步數
{
    int pos;
    int step;
}Node;

bool operator < (Node a, Node b)  //重載運算符,定義元素加入隊列的準則
{
    return a.step > b.step;
}

Node start;    //開始位置,步數
priority_queue <Node> pq;     //優先隊列
int Sn[MAXN], Lz[MAXN];       //記錄蛇頭蛇尾,梯子頭/梯子尾
int Si, Ei, res, v[MAXN];     
int N, S, L;
const int dir[] = {1, 2, 3, 4, 5, 6};  //骰子

bool check(int x)  //走下一步要滿足的條件
{
    return x>0 && x<=N*N && !v[x];
}

int BFS()
{
    Node cur;
    int x, xx, value;
    while(!pq.empty()) {
        cur = pq.top(), pq.pop();
        x = cur.pos, value = cur.step;
        for(int i=0; i<6; i++) {
            xx = x + dir[i];
            if(check(xx)) {
                v[xx] = 1;
                if(xx == N*N) return value+1;
                if(Sn[xx] != 0 && !v[Sn[xx]]) {      //如果踩中蛇頭,判斷蛇尾是否訪問過,如果沒有訪問過則壓進隊列,否則不用處理;梯子也是一樣;
                    cur.pos = Sn[xx], cur.step = value+1;
                    pq.push(cur);
                }
                if(Lz[xx] != 0 && !v[Lz[xx]]) {
                    cur.pos = Lz[xx], cur.step = value+1;
                    pq.push(cur);
                }
            }
        }
    }
    return -1;
}

int main(int argc, char *argv[])
{
    while(~scanf("%d %d %d", &N, &S, &L)) {
        RST(Sn), RST(Lz), RST(v);
        for(int i=0; i<S; i++) {   //記錄蛇頭蛇尾
            scanf("%d %d", &Si, &Ei);
            Sn[Si] = Ei;
        }
        for(int i=0; i<L; i++) {   //記錄梯子頭和梯子尾
            scanf("%d %d", &Si, &Ei);
            Lz[Si] = Ei;
        }
        while(!pq.empty()) pq.pop();   //清空隊列
        v[1] = 1;
        start.pos = 1, start.step = 0;
        pq.push(start);
        res = BFS();
        if(res != -1) printf("%d\n", res);
    }
    return 0;
}

/*
測試數據:
Sample Input:
6 1 3
35 25
3 23 5 16 20 33
Sample Output:
3
*/



發佈了188 篇原創文章 · 獲贊 26 · 訪問量 28萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章