优先队列问题(此题来源哈尔滨理工大学VJ)

---恢复内容开始---

Description

小z身处在一个迷宫中,小z每分钟可以走到上下左右四个方向的相邻格之一。迷宫中有一些墙和障碍物。
同时迷宫中也有一些怪兽,当小z碰到任意一个怪兽时,小z需要将怪兽消灭掉才可以离开此方格。但消灭
怪兽会花费一定的时间。现在小z想知道走出迷宫需要花费的最少时间。

Input

输入第一行为组数T(T<=10)。

对于每组数据第一行为两个整数R和C(1<=R,C<=200)。以下R行每行有C个字符,即迷宫地图。

其中"#"代表墙和障碍物,"."表示空地,[1~9]的数字代表此处有怪兽以及消灭此处的怪兽需要的时间.

"Z"表示小z的起始位置,"W"表示迷宫出口。

对于每组数据保证起始位置和迷宫出口唯一。

Output

对于每组数据,输出走出迷宫的最短时间(单位:分钟)。如果无法走出迷宫则输出"IMPOSSIBLE"。

Sample Input

2
3 4
.Z..
.234
#.W.
4 4
Z.1.
.32.
##4.
W#..

Sample Output

5
IMPOSSIBLE仅用普通的搜索会WA掉,此题是我遇到的第一个区分时间优先和路径优先的题,以前的问题大体上是寻找最短路径,计算走最短路径需要的时间;这道题特点是既有路径,又有时间,并且他俩又互相影响,这时我们便要考虑优先级的问题,根据题一可知:时间优先,所以我们需要使用优先队列这里简单介绍一下优先队列的使用优先队列要引用头文件<queue>定义为priority_queue<类型>名称;用法和队列一样,优先级要用重载来完成一种是重载‘<‘来完成,需要在结构体内来重载,这里在一个结构体内演示一下struct into{   string name;  double score;  bool operator < (const into &a) const {  return a.score<score; )};还可以类似sort定义重载优先级需要使用头文件<vector>,同样举例说明priority_queue<int,vector<int>,mycomper>pq;//引用方法;struct mycomper{  bool operator () (const int &a,const int &b)  {   return a>b;  }};如果会了优先队列,那么这道题就变得简单多了我附代码:
#include<iostream>
#include<string.h>
#include<queue>
#include<ctype.h>
#include<vector>
using namespace std;
int m,n;
char maps[201][201];
int vis[201][201];
int dirx[4]= {1,-1,0,0};
int diry[4]= {0,0,1,-1};
struct point
{
    int x;
    int y;
    int step;
    bool operator <(const point &a) const
    {
        return a.step<step;
    }
};
int bfs(struct point start)
{
    memset(vis,0,sizeof(vis));
    priority_queue<point>que;
    que.push(start);
    vis[start.x][start.y]=1;
    point temp,cur;
    while(!que.empty())
    {
        temp=que.top();
        que.pop();
        if(maps[temp.x][temp.y]==‘W‘)
        {
            return temp.step;
        }
        for(int i=0; i<4; i++)
        {
            cur.x=temp.x+dirx[i];
            cur.y=temp.y+diry[i];
            if(cur.x>=0&&cur.x<m&&cur.y>=0&&cur.y<n&&maps[cur.x][cur.y]!=‘#‘&&vis[cur.x][cur.y]==0)
            {
                if((maps[cur.x][cur.y])>=‘0‘&&maps[cur.x][cur.y]<=‘9‘)
                {
                    int cun=maps[cur.x][cur.y]-‘0‘+1;
                    cur.step=temp.step+cun;
                    vis[cur.x][cur.y]=1;
                    que.push(cur);

                }
                else
                {
                    cur.step=temp.step+1;
                    vis[cur.x][cur.y]=1;
                    que.push(cur);

                }
                //cout<<cur.step<<maps[cur.x][cur.y]<<endl;

            }
        }
    }
    return -1;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>m>>n;
        point start;
        for(int i=0; i<m; i++)
        {
            for(int j=0; j<n; j++)
            {
                cin>>maps[i][j];
                if(maps[i][j]==‘Z‘)
                {
                    start.x=i;
                    start.y=j;
                    start.step=0;
                }
            }
        }
        int ans=bfs(start);
        if(ans==-1) cout<<"IMPOSSIBLE"<<endl;

        else cout<<ans<<endl;
    }
}
  

---恢复内容结束---

时间: 2024-10-18 01:04:50

优先队列问题(此题来源哈尔滨理工大学VJ)的相关文章

开锁魔法II 哈尔滨理工大学第五届ACM程序设计竞赛

规律:a[i][j]=     1/i * a[i-1][j-1]      +      (i-1)/i * a[i-1][j];  (少一个盒子时使用j-1 次魔法的概率)   (少一个盒子时使用j次魔法的概率) 公式推导如下: 设a[i][j]为打开i个盒子正好需要j次魔法的情况. ① 1->1 ② 1->1 , 2->2;        两次 1->2 , 2->1;        一次 ③ 1->1 , 2->2 , 3->3;     三次 1-

哈尔滨理工大学2016新生赛B题

做为长城上的卫士,影踪派一直守在螳螂高原上防止螳螂人卡拉克西的入侵.影踪派的长城可以近似看做是一条直线上依次编号为1~N的N个基地组成,编号相邻的两个基地之间由长城相连接,而影踪派掌门祝踏岚所在的影踪禅院位于编号为1的基地.     祝踏岚发现,每次螳螂人只会选择长城上的一个基地进行猛烈的攻击,所以,祝踏岚每次都要从影踪禅院赶到被攻击的基地亲临前线指挥战斗.但是,在长城上移动是很耗时的,为了能更快的赶到任何一个可能被攻击的基地,祝踏岚决定修建一对传送门.     一对传送门由两个入口组成,它能实

哈尔滨理工大学2016新生赛D题

陈月亮从小就热爱数学,这天老师讲到任何一个正整数N,我们可以很容易的找出N的所有因子,N1,N2,N3...,Nk,称N一共有k个因子(包含1和N本身). 求出k的值这个问题对于陈月亮来说实在是太简单了,于是她想要求出N所有因子的因子个数(如N1可能包含n1个因子(包含1和N1本身),N2可能包含n2个因子,...,Nk可能包含nk个因子),然后计算出S的值: 第一行为一个整数T(T <= 10000),代表测试数据的组数. 接下来T行每行一个正整数N(N < 2 ^ 31). 对于每组测试数

哈尔滨理工大学2016新生赛H题

陈月亮最喜欢的季节就是冬天了,这不看着窗外飘起了雪花,陈月亮开心的跑出屋来看雪.但是迷迷糊糊的陈月亮不知道自己是在做梦还是真的下起了雪.突然她想起了一句话,在真实世界中是没有两片一样的雪花的.于是你的任务就是比较这场雪中的所有雪花,如果出现了两朵完全一致的雪花,则证明陈月亮是在梦中. 每朵雪花用六个整数表示,范围在(1 – 10000000)之间,表示雪花六个花瓣的长度,六个整数的先后出现顺序可能是顺时针顺序也可能是逆时针顺序,并且可能是从任意一个花瓣开始的.比如说对同一个花瓣,描述方法可能是1

哈尔滨理工大学2016新生赛A题

一名骑着马的强盗闯进了原本平静祥和的棋盘村,为了通知村里的士兵来打败强盗,你必须要通知位于棋盘村最下方的兵营.棋盘村的地形就像是一张棋盘,你所在的位置为A点(0,0),兵营位于棋盘村的右下角B点(n,m).你每次只能走一步,可以选择向下走,也可以选择向右走.但是强盗所在的位置和强盗的马一次所能跳到的位置是不可以走过去的(强盗的马的移动方法与象棋中的马相同).请计算出从A点能够走到B点的所有路径条数. 首先输入一个整数t,代表有t组测试数据. 每组测试数据为四个整数,即B点的坐标(n,m)和强盗的

哈尔滨理工大学2016新生赛F题

给出两个正整数m,n,在笛卡尔坐标系中选出四个不同的点,满足: (1)   点的横坐标是一个在区间[0,m]的整数. (2)   点的纵坐标是一个在区间[0,n]的整数. (3)   这四个点做顶点构成一个菱形. 有多少种满足以上条件的选择方法呢? Input 多组测试数据,每组输入两个正整数m,n(m <= 1000, n <= 1000). 处理到文件结束. Output 每行输出一个整数,表示有多少满足条件的选择方法. Sample Input 2 2 Sample Output 6 #

哈尔滨理工大学2016新生赛C题

一个r行c列的矩阵里的所有元素都为0或1,给出这个矩阵每一行的和以及每一列的和,那么是否存在这样一个矩阵满足条件呢,如果存在任意一个满足条件的矩阵则输出YES,如果不存在则输出NO? 每组测试数据第一行包含两个整数r,c,表示矩阵的行数和列数. 第二行包含r个32位无符号数,表示矩阵每行的和. 第三行包含c个32位无符号数,表示矩阵每列的和. (1 <= r,c <= 100000) 如果存在这样的一个01矩阵,输出YES,否则输出NO 首先需要判断行和列的总和是否相等,因为它们都应该是整个矩

哈尔滨理工大学2016新生赛I题

这次我们要写一个简单的行编辑器,当按下'#'时代表按下了一次退格符,当按下'@'时代表一个退行符(使当前行的字符全部无效).例如,假设从终端接收了这样的两行字符: Whil#lr#e(s#*s) [email protected](*s=#++) 则实际有效的是下列两行: While(*s) putchar(*s++) 请你编写一个程序,输出实际有效的字符串. 第一行是一个整数T,表示测试数据组数. 接下来每行为一个字符串(不含空格和任何空白),表示输入的原始字符串 输出最终的正确字符串. 2

哈尔滨理工大学2016新生赛E题

多组数据,每组测试数据输入9个整数,为1-9的一个全排列.初始状态会被描述为 1 2 3 4 5 6 7 8 9 Output 输出所需要的最小移动步数. Sample Input 1 2 3 4 5 6 7 8 9 9 8 7 6 5 4 3 2 1 Sample Output 0 12 将每个排列利用康托展开压缩为一个整数,采用广度优先搜索的方式不停的搜索直到得到目标状态即可. #include <stdio.h> #include <string.h> const int M