校赛 问题 F: 传送门(Dijkstra算法)

问题 F: 传送门

时间限制: 1 Sec  内存限制: 128 MB

题目描述

嘎鱼有一个传送门迷宫缩略图,缩略图上'.'代表着这是一块空地,'#'代表是一堵墙。他现在所在的位置是'@',目的地是'$'。嘎鱼从起始地出发,只能上下左右移动,不能穿过或者破坏墙壁,每次走一格需要消耗一点体力。与此同时,地图中会有一些单向传送门,分别用大写字母A-Z代表传送门起点,小写字母a-z代表传送门终点。嘎鱼可以在传送门的格子时,可以选择不使用传送门,此时该地当成一个空地。若使用传送门,则需要花费钱,且能够立刻从大写字母传到对应该字母的小写字母所在地且不消耗体力,但是没有办法再传送回去,同样的,小写字母也可以看成是一格空地。

嘎鱼身体精力和资源有限,他想知道到达目的地(题目保证肯定可达),在最优路线下,消耗多少体力与金钱,最优路线应保证消耗体力最少,若有多条路线可以消耗最少体力,则应选择花费最少的那条路线。

输入

第一行是一个整数T,代表样例组数

第二行是两个整数,分别代表缩略图的行数r和列数c (r ,c <= 100)

接下来是r行长度为c的字符串

最后一行是26个数字,分别对应每种传送门所需要花费的金钱

输出

两个用空格隔开的整数,第一个是体力消耗,第二个是金钱消耗。

样例输入

1
5 5
$.a##
.@##A
#....
.....
.....

1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

样例输出

2 0

解析:
这道题我们一开始用了普通的bfs,结果超时了,后来才知道要用到Dijkstra算法,因为边权不一样......
感觉自己真的好愚钝啊,一个Dijkstra算法研究了大概一个星期才基本搞明白了。
以下是AC代码:
#include
using namespace std;
typedef pair<int,int> P;
const int N=100+10;
const int dx[]= {-1,0,0,1};
const int dy[]= {0,-1,1,0};
char a[N][N];
int d[N][N];
int c[N][N];
int m,n,start[2],dest[2];
int cost_a[155],pos_a[155][2];
bool ok(int x,int y)
{
    return x>=0&&x<=m-1&&y>=0&&y<=n-1&&a[x][y]!='#';
}
struct cmp
{
    bool operator()(const P& p1,const P& p2)const
    {
        int x=p1.first,y=p1.second,x2=p2.first,y2=p2.second;
        return d[x][y]>d[x2][y2]||(d[x][y]==d[x2][y2]&&c[x][y]>c[x2][y2]);
    }
};
void Dijkstra()
{
    memset(d,0x3f3f,sizeof d);
    memset(c,0x3f3f,sizeof c);
    d[dest[0]][dest[1]]=c[dest[0]][dest[1]]=0;
    priority_queue,cmp > q;
    q.push(P(dest[0],dest[1]));
    while(!q.empty())
    {
        int x=q.top().first,y=q.top().second;
        q.pop();
        int dis=d[x][y],cost=c[x][y];
        if(dis>d[start[0]][start[1]]||(dis==d[start[0]][start[1]]&&cost>c[start[0]][start[1]]))
            continue;
        for(int i=0; i<4; ++i)
        {
            int x2=x+dx[i],y2=y+dy[i];
            if(ok(x2,y2)&&(d[x2][y2]>dis+1||(d[x2][y2]==dis+1&&c[x2][y2]>cost)))
            {
                d[x2][y2]=dis+1,c[x2][y2]=cost;
                q.push(P(x2,y2));
            }
        }
        if(islower(a[x][y]))
        {
            int x2=pos_a[a[x][y]][0],y2=pos_a[a[x][y]][1];
            if(d[x2][y2]>dis||(d[x2][y2]==dis&&c[x2][y2]>cost+cost_a[a[x][y]]))
            {
                d[x2][y2]=dis,c[x2][y2]=cost+cost_a[a[x][y]];
                q.push(P(x2,y2));
            }
        }
    }
}
int main()
{
    //freopen("i.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&m,&n);
        for(int i=0; ii)
            for(int j=0; jj)
            {
                char ch;
                scanf(" %c",&ch);
                if(ch=='$')
                    dest[0]=i,dest[1]=j;
                else if(ch=='@')
                    start[0]=i,start[1]=j;
                else if(isupper(ch))
                    pos_a[tolower(ch)][0]=i,pos_a[tolower(ch)][1]=j;
                a[i][j]=ch;
            }
        for(char ch='a'; ch<='z'; ++ch)
            scanf("%d",&cost_a[ch]);
        Dijkstra();
        printf("%d %d\n",d[start[0]][start[1]],c[start[0]][start[1]]);
    }
    return 0;
}
 
   

编辑人:ltx

 

转载于:https://www.cnblogs.com/ncc62497/p/8966973.html

你可能感兴趣的:(校赛 问题 F: 传送门(Dijkstra算法))