【STL】棧+隊列+優先隊列(詳)+ 拯救行動題解

1、棧前端

      棧(stack)又名堆棧,它是一種運算受限的線性表。其限制是僅容許在表的一端進行插入和刪除運算。這一端被稱爲棧頂,相對地,把另外一端稱爲棧底。向一個棧插入新元素又稱做進棧、入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成爲新的棧頂元素;從一個棧刪除元素又稱做出棧或退棧,它是把棧頂元素刪除掉,使其相鄰的元素成爲新的棧頂元素。node

    說通俗一點,就是一種有口無肛門的數據結構 咳咳...是一種知足「後進先出」規則的數據結構。有PUSH和POP兩種操做。PUSH:把元素壓入棧頂 POP:把元素從棧頂彈出ios

棧定義在頭文件<stack>中,用「stack<int> s」申明一個棧後端

↑_↑以上的都很是基礎數據結構

2、隊列spa

      隊列是一種特殊的線性表,特殊之處在於它只容許在表的前端(front)進行刪除操做,而在表的後端(rear)進行插入操做,和棧同樣,隊列是一種操做受限制的線性表。進行插入操做的端稱爲隊尾,進行刪除操做的端稱爲隊頭。
      說通俗一點,就是一種 有口有肛門的 咳咳...是符合「先進先出」原則的公平隊列。
隊列定義在頭文件<queue>中,用「queue<int> q」申明一個隊列,用push(),pop()進行入隊出隊,front()取隊首元素,但不刪除√
↑_↑以上的仍是很是基礎
 
3、優先隊列
  在優先隊列中,元素被賦予優先級。當訪問元素時,具備最高優先級的元素最早刪除。優先隊列具備最高級先出 (first in, largest out)的行爲特徵。
  優先隊列定義在頭文件<queue>中,用「priority_queue<int> q」申明一個隊列用push(),pop()進行入隊出隊,top()取隊首元素,但不刪除√ empty()隊列是否爲空
用優先隊列是時候咱們必須先對每個元素定義一個優先級,這樣就須要重載運算符。
好比,咱們要定義一個「個位數大的優先級小」的優先隊列能夠這麼寫↓_↓
/*
定義一個結構體cmp,重載「()」運算符
用「priority_queue<int, vector<int>, cmp> q」定義 
*/
struct cmp
{
    bool operator() (const int a, const int b)//a的優先值小於b返回true 
    const
    {
        return a % 10 > b % 10;
    }
};

若是要定義「越小的整數優先值越大」的優先隊列,能夠直接用這個:priority_queue<int, vector<int>, grater<int> >qcode

而後有一道題↓_↓blog

openjudge-4980:拯救行動

描述

公主被惡人抓走,被關押在牢房的某個地方。牢房用N*M (N, M <= 200)的矩陣來表示。矩陣中的每項能夠表明道路(@)、牆壁(#)、和守衛(x)。 
英勇的騎士(r)決定孤身一人去拯救公主(a)。咱們假設拯救成功的表示是「騎士到達了公主所在的位置」。因爲在通往公主所在位置的道路中可能遇到守衛,騎士一旦遇到守衛,必須殺死守衛才能繼續前進。 
現假設騎士能夠向上、下、左、右四個方向移動,每移動一個位置須要1個單位時間,殺死一個守衛須要花費額外的1個單位時間。同時假設騎士足夠強壯,有能力殺死全部的守衛。隊列

給定牢房矩陣,公主、騎士和守衛在矩陣中的位置,請你計算拯救行動成功須要花費最短期。ci

輸入

第一行爲一個整數S,表示輸入的數據的組數(多組輸入)
隨後有S組數據,每組數據按以下格式輸入 
一、兩個整數表明N和M, (N, M <= 200). 
二、隨後N行,每行有M個字符。"@"表明道路,"a"表明公主,"r"表明騎士,"x"表明守衛, "#"表明牆壁。

輸出

若是拯救行動成功,輸出一個整數,表示行動的最短期。
若是不可能成功,輸出"Impossible"

樣例輸入

2
7 8
#@#####@
#@a#@@r@
#@@#x@@@
@@#@@#@#
#@@@##@@
@#@@@@@@
@@@@@@@@ 
13 40
@x@@##x@#x@x#xxxx##@#x@x@@#x#@#x#@@x@#@x
xx###x@x#@@##xx@@@#@x@@#x@xxx@@#x@#x@@x@
#@x#@x#x#@@##@@x#@xx#xxx@@x##@@@#@x@@x@x
@##x@@@x#xx#@@#xxxx#@@x@x@#@x@@@x@#@#x@#
@#xxxxx##@@x##x@xxx@@#x@x####@@@x#x##@#@
#xxx#@#x##xxxx@@#xx@@@x@xxx#@#xxx@x#####
#x@xxxx#@x@@@@##@x#xx#xxx@#xx#@#####x#@x
xx##@#@x##x##x#@x#@a#xx@##@#@##xx@#@@x@x
x#x#@x@#x#@##@xrx@x#xxxx@##x##xx#@#x@xx@
#x@@#@###x##x@x#@@#@@x@x@@xx@@@@##@@x@@x
x#xx@x###@xxx#@#x#@@###@#@##@x#@x@#@@#@@
#@#x@x#x#x###@x@@xxx####x@x##@x####xx#@x
#x#@x#x######@@#x@#xxxx#xx@@@#xx#x#####@

樣例輸出

13
7

拿到這道題之後能夠發現是一個很簡單的廣搜,以時間爲優先級,代碼以下↓_↓
#include<stdio.h>
#include<iostream>
#include<queue>
using namespace std;
int n, m;
int dx[4] = {1,-1,0,0},
    dy[4] = {0,0,1,-1};
char map[201][201];
bool flag;
struct node//重載運算符,以時間爲優先級 
{
    int x, y, step;
    friend bool operator < ( node a, node b)
    {
        return a.step > b.step;
    }
}www, mmm;
priority_queue<node> q;
int main()
{
    int i, j, s;
    int sx, sy;
    scanf("%d", &s);
    while(s--)
    {
        while(!q.empty())q.pop();//注意!!必定要清空隊列,這裏寫錯調了一個下午的我...機房出現野生崩潰餅... 
        scanf("%d%d", &n, &m);
        for(i = 1; i <= n; i++)
        {
            for(j = 1; j <= m; j++)
            {
                cin>>map[i][j];//不要問我爲何用cin→_→,我只是懶 
                if(map[i][j] == 'r'){sx = i; sy = j;}
            }
        }            
        www.x = sx; www.y = sy; www.step = 0; map[sx][sy] = '#';
        q.push(www);
        flag = 0;
        while(!q.empty())//隊列不爲空 
        {
            www = q.top();//取隊首元素 
            q.pop();//彈出隊首元素 
            for(i = 0; i <= 3; i++)
            {
                mmm.x = www.x+dx[i];
                mmm.y = www.y+dy[i];
                mmm.step = www.step+1;
                if(mmm.x<1||mmm.y<1||mmm.x>n||mmm.y>m) continue;
                if(map[mmm.x][mmm.y] == '#') continue;
                if(map[mmm.x][mmm.y] == '@') {q.push(mmm);}//元素入隊 
                if(map[mmm.x][mmm.y] == 'x') {mmm.step++; q.push(mmm);}
                if(map[mmm.x][mmm.y] == 'a') {printf("%d\n", mmm.step); flag = 1; break;}
                map[mmm.x][mmm.y] = '#';
            }
            if(flag) break;
        }
        if(!flag) printf("Impossible\n");
    }
    return 0;
}

優先隊列的基本用法完結~\(≧▽≦)/~啦啦啦

相關文章
相關標籤/搜索