首页 > 代码库 > 【STL】栈+队列+优先队列(详)+ 拯救行动题解

【STL】栈+队列+优先队列(详)+ 拯救行动题解

一、栈

      栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

    说通俗一点,就是一种有口无肛门的数据结构 咳咳...是一种满足“后进先出”规则的数据结构。有PUSH和POP两种操作。PUSH:把元素压入栈顶 POP:把元素从栈顶弹出

栈定义在头文件<stack>中,用“stack<int> s”申明一个栈

↑_↑以上的都非常基础

二、队列

      队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
      说通俗一点,就是一种有口有肛门的 咳咳...是符合“先进先出”原则的公平队列。
队列定义在头文件<queue>中,用“queue<int> q”申明一个队列,用push(),pop()进行入队出队,front()取队首元素,但不删除√
↑_↑以上的还是非常基础
 
三、优先队列
  在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (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> >q

然后有一道题↓_↓

openjudge-4980:拯救行动

描述

公主被恶人抓走,被关押在牢房的某个地方。牢房用N*M (N, M <= 200)的矩阵来表示。矩阵中的每项可以代表道路(@)、墙壁(#)、和守卫(x)。 
英勇的骑士(r)决定孤身一人去拯救公主(a)。我们假设拯救成功的表示是“骑士到达了公主所在的位置”。由于在通往公主所在位置的道路中可能遇到守卫,骑士一旦遇到守卫,必须杀死守卫才能继续前进。 
现假设骑士可以向上、下、左、右四个方向移动,每移动一个位置需要1个单位时间,杀死一个守卫需要花费额外的1个单位时间。同时假设骑士足够强壮,有能力杀死所有的守卫。

给定牢房矩阵,公主、骑士和守卫在矩阵中的位置,请你计算拯救行动成功需要花费最短时间。

输入

第一行为一个整数S,表示输入的数据的组数(多组输入)
随后有S组数据,每组数据按如下格式输入 
1、两个整数代表N和M, (N, M <= 200). 
2、随后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;
}

优先队列的基本用法完结~\(≧▽≦)/~啦啦啦

【STL】栈+队列+优先队列(详)+ 拯救行动题解