数据结构_优先队列

本文介绍了一种基于贪心算法的游戏地图寻路方法,通过优先队列实现s_sin角色从起点到终点的最短路径计算,考虑了不同地形对移动时间的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

正如你所知道的s_sin是一个贪玩的不得了的小P孩QAQ,你也知道他最近很喜欢玩一个叫做太阳帝国的原罪的策略游戏去年他已经和疯狂的AI交战了整整一年。而现在,战斗的序幕又要拉开了。
在某个星球上,该星球由n*m个方格组成,每个方格中可能为boss,s_sin,障碍,道路,小怪。s_sin想要去打爆boss,假设他可以秒杀boss,现在他的任务只需要到达boss所在的位置。如果s_sin想要到达某个方格,但方格中有小怪,那么必须打死小怪,才能到达这个方格。假设s_sin只能向上、下、左、右移动一个格子,移动一步用时1个时间单位,杀死小怪也用1个时间单位。假设s_sin很强壮,可以杀死所有小怪。
试计算s_sin到达boss位置至少需要多少时间。注意:障碍时不能通过的。
★数据输入
输入第一行为两个正整数n,m (1 < =n,m< =100), 表示该地图有n行m列。
接下来n行,每行m个字符:“.”代表道路, “a”代表boss , “r”代表s_sin ,“#”代表障碍,“x”代表小怪。
★数据输出
如果s_sin能到达boss位置则输出所需的最少时间。如果无法达到,则输出-1

 

7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##..
.#......
........

 

13

 

 

 

1."."与'a'都是没哟停留时间的,但每走一次都需要1个单位时间,所以还是假设他们的权值为1

2.'x' 停留时间1个单位加上走需要一个单位时间,权值时间为2个单位

3.每次取出优先队列的首个元素,然后对它的上下左右点做判断,满足一定条件的点push到队列里,更新vis数组

 

 
            #include<cstdio>
#include<queue>
using namespace std;
struct node
{
    int x,y,dis;
    bool operator<(const node &b)const{
    return dis>b.dis;}
};
priority_queue<node> q;
const int N=105;
char G[N][N];
bool vis[N][N];
int n,m;
int get_value(const node &cur)
{
    switch(G[cur.y][cur.x])
    {
    case '.':
    case 'a':
        return 1;
    case 'x':
        return 2;
    }
    return 0;
}
void move_out(const node &cur)
{
    int i,tmp[]={0,0,1,-1};
    node next;
    for(i=0;i<4;++i)
    {
        next.x=cur.x+tmp[i],next.y=cur.y+tmp[3-i];
        if(next.y<0||next.y>=n||next.x<0||next.x>=m)continue;
        if(!vis[next.y][next.x]&&G[next.y][next.x]!='#')
        {

            next.dis=cur.dis+get_value(next);
            q.push(next);
        }
        vis[next.y][next.x]=true;

    }
}
int search_map(const node &start,const node&end)
{
    node cur;
    vis[start.y][start.x]=true;
    q.push(start);
    while(!q.empty())
    {
        cur=q.top();q.pop();
       // printf("y->%d x->%d\n",cur.y,cur.x);
        if(cur.x==end.x&&cur.y==end.y)return cur.dis;
        move_out(cur);
    }
    return -1;

}
int main()
{
    int i,j,flag;
    node start,end;
    scanf("%d %d",&n,&m);
    for(i=0;i<n;++i){
        scanf("%s",G[i]);
    }
    for(i=0,flag=0;i<n;++i)
        for(j=0;j<m;++j)
        {
            if(flag==2)break;
            if(G[i][j]=='r')start.x=j,start.y=i,start.dis=0,flag++;
            if(G[i][j]=='a')end.x=j,end.y=i,flag++;
        }

    printf("%d\n",search_map(start,end));
}

        


 

 做个小小优化

当“观察”取出点的上下左右中发现终点,则程序结束

#include<cstdio>
#include<queue>
using namespace std;
struct node
{
    int x,y,dis;
    bool operator<(const node &b)const{
    return dis>b.dis;}
};
priority_queue<node> q;
const int N=105;
char G[N][N];
bool vis[N][N];
int n,m;
int get_value(const node &cur)
{
    switch(G[cur.y][cur.x])
    {
    case '.':
    case 'a':
        return 1;
    case 'x':
        return 2;
    }
    return 0;
}
int move_out(const node &cur,const node &end)
{
    int i,tmp[]={0,0,1,-1};
    node next;
    for(i=0;i<4;++i)
    {
        next.x=cur.x+tmp[i],next.y=cur.y+tmp[3-i];
        if(next.y<0||next.y>=n||next.x<0||next.x>=m)continue;
        if(!vis[next.y][next.x]&&G[next.y][next.x]!='#')
        {

            next.dis=cur.dis+get_value(next);
            if(next.x==end.x&&next.y==end.y)return next.dis;
            q.push(next);
        }
        vis[next.y][next.x]=true;
    }
    return -1;
}
int search_map(const node &start,const node&end)
{
    node cur;
    int ans=-1;
    vis[start.y][start.x]=true;
    q.push(start);
    while(!q.empty())
    {
        cur=q.top();q.pop();
       // printf("y->%d x->%d\n",cur.y,cur.x);
        if(cur.x==end.x&&cur.y==end.y)return cur.dis;
        ans=move_out(cur,end);
        if(ans>-1)return ans;
    }
    return -1;

}
int main()
{
    int i,j,flag;
    node start,end;
    scanf("%d %d",&n,&m);
    for(i=0;i<n;++i){
        scanf("%s",G[i]);
    }
    for(i=0,flag=0;i<n;++i)
        for(j=0;j<m;++j)
        {
            if(flag==2)break;
            if(G[i][j]=='r')start.x=j,start.y=i,start.dis=0,flag++;
            if(G[i][j]=='a')end.x=j,end.y=i,flag++;
        }

    printf("%d\n",search_map(start,end));
}


 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值