《挑戰程序設計競賽》P34迷宮的最短路徑

/*
注意pair的使用和定義,注意4個方向向量的處理,注意標記的處理
BFS(寬度優先搜索)按照距開始狀態由近及遠的順序進行搜索,因此可以很容易地用來求最短路徑、
最少操作之類的答案
*/
/*
(轉)
pair的類型:
pair 是 一種模版類型。每個pair 可以存儲兩個值。這兩種值無限制。也可以將自己寫的struct的對象放進去。。
pair<string,int> p;
pair<int ,int > p;
pair<double,int> p;
都可以。。。
<span style="font-family: Arial, Helvetica, sans-serif;">應用:如果一個函數有兩個返回值 的話,如果是相同類型,就可以用數組返回,如果是不同類型,就可以自己寫個struct ,但爲了方便就可以使用 c++  自帶的pair ,返回一個pair,其中帶有兩個值。除了返回值的應用,在一個對象有多個屬性的時候 ,一般自己寫一個struct ,如果就是兩個屬性的話,就可以用pair 進行操作。。。</span>
應用pair 可以省的自己寫一個struct 。。。如果有三個屬性的話,其實也是可以用的pair 的 ,極端的寫法 pair <int ,pair<int ,int > >
寫法極端。(後邊的兩個 > > 要有空格,否則就會是 >>  位移運算符)
makr_pair:
pair<int ,int >p (5,6);
pair<int ,int > p1= make_pair(5,6);
pair<string,double> p2 ("aa",5.0);
pair <string ,double> p3 = make_pair("aa",5.0);
有這兩種寫法來生成一個pair。

 如何取得pair的值呢。。
 每個pair 都有兩個屬性值  first  和second
 cout<<p1.first<<p1.second;
 注意是屬性值而不是方法。

template <class T1, class T2> struct pair
{
  typedef T1 first_type;
  typedef T2 second_type;

  T1 first;
  T2 second;
  pair() : first(T1()), second(T2()) {}
  pair(const T1& x, const T2& y) : first(x), second(y) {}
  template <class U, class V>
    pair (const pair<U,V> &p) : first(p.first), second(p.second) { }
}
由於pair類型的使用比較繁瑣,因爲如果要定義多個形同的pair類型的時候,可以時候typedef簡化聲明:
typedef pair<string, string> author;
author pro("May", "Lily");
author joye("James", "Joyce");
*/
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <cstring>
#include <utility>

using namespace std;

#define ll long long
#define llu unsigned long long
#define INF 100000000

//使用pair表示狀態時,使用typedef會更加方便一些
const int maxn = 100+10;
typedef pair<int, int> P;
char maze[maxn][maxn];//表示迷宮的字符串數組
int n,m;
int sx,sy;//起點座標
int gx,gy;//重點座標
int d[maxn][maxn]; //到各個位置的最短距離的數組
//四個方向移動的向量
int dx[4] = {1,0,-3 2 1 4 5 7 6
3 1 2 5 6 7 4
7 8 11 3 5 16 12 18
8 3 11 7 16 18 12 5
255
2551,0}, dy[4] = {0,1,0,-1};

//求從(sx,sy)到(gx,gy)的最短距離
//如果無法到達,則是INF
int bfs()
{
    queue<P > que;
    // 把所有的位置都初始化爲INF
    for(int i = 0; i < n; ++i)
        for(int j = 0; j < m; ++j) d[i][j] = INF;
    //將起點加入隊列,並把這一地點的距離設置爲0
    que.push(P(sx,sy));
    d[sx][sy] = 0;
    //不斷循環直到隊列的長度爲0
    while(que.size()) //while(!que.empty())
    {
        //從隊列的最前端取出元素
        P p = que.front();
//        cout << p.first << " " << p.second << endl;
        que.pop();
        //如果取出的狀態已經是終點,則結束搜索
        if(p.first == gx && p.second == gy) break;
        //四個方向的循環
        for(int i = 0; i < 4; ++i)
        {
            //移動之後的位置記爲(nx,ny)
            int nx = p.first + dx[i],ny = p.second + dy[i];
            //判斷是否可以移動以及是否已經訪問過(d[nx][ny] != INF即爲已經訪問過)
            if(0 <= nx && nx < n && 0 <= ny && ny < m && maze[nx][ny] != '#'
                    && d[nx][ny] == INF)
            {
                //可以移動的話則加入隊列,並且到該位置的距離確定爲到p的距離+1
                que.push(P(nx,ny));
                d[nx][ny] = d[p.first][p.second] + 1;
            }
        }
    }
    return d[gx][gy];
}
void solve()
{
    int res = bfs();
    printf("%d\n",res);
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
#endif // ONLINE_JUDGE
    while(cin >> n >> m)
    {
        memset(maze,0,sizeof(maze));
        for(int i = 0; i < n; ++i)
            for(int j = 0; j < m; ++j)
            {
                cin >> maze[i][j];
                if(maze[i][j] == 'S') {sx = i; sy = j;}
                if(maze[i][j] == 'G') {gx = i; gy = j;}
            }
//        cout << sx << " " << sy << endl;
//        for(int i = 0; i < n; ++i)
//        {
//            for(int j = 0; j < n; ++j)
//                cout << maze[i][j];
//            cout << endl;
//        }
        solve();
    }
    return 0;
}
/*
Sample Input:
10 10
#S######.#
......#..#
.#.##.##.#
.#........
##.##.####
....#....#
.#######.#
....#.....
.####.###.
....#...G#
Sample Output:
22
*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章