URAL 1643 Attack of the Dark Fortress BFS

从阎宝
2023-12-01

题目链接:点击打开链接

题意:

'$'和'!'是2个人,'*'是终点。

'A'-'Z' 字母是26种传送门,每种传送门可以到瞬间同字母(不同字母间不能移动)

问2个人中慢的那个到达终点的步数。

可以往8个方向走。

思路:

bfs

把同字母的点当成一个点。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
#define N 10115
#define M (N*33)
struct Edge{
    int to, dis, nex;
}edge[M];
int head[N], edgenum;
int step[8][2] = {-1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1};
void init(){memset(head, -1, sizeof head); edgenum = 0;}
void add(int u, int v, int d){
    Edge E = {v, d, head[u]};
    if(edgenum>=M)while(1);
    edge[edgenum] = E;
    head[u] = edgenum++;
}
int n, m;
char s[115][115];
bool inmap(int x, int y){return 1<=x&&x<=n&&1<=y&&y<=m && s[x][y]!='#';}
void put(int dis[]){int top = 1; for(int i = 1; i <=n; i++){for(int j= 1;j<=m;j++)printf(" %d",dis[top++]);puts("");}}
int Hash(int x, int y){return (x-1)*m+y;}
bool inq[N];
int bfs(int from, int to, int dis[]){
    int top = 1;
	for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++){
            dis[top++] = -1;
	}
    memset(inq, 0, sizeof inq);
    dis[from] = 0;
    queue<int>q; q.push(from);
    while(!q.empty()){
        int u = q.front(); q.pop(); inq[u] = 0;
        for(int i = head[u]; ~i; i = edge[i].nex){
            int v = edge[i].to;
            if(dis[v]==-1 || dis[v]>dis[u]+edge[i].dis){
                dis[v] = dis[u]+edge[i].dis;
                if(!inq[v] && v!=to)inq[v] = 1, q.push(v);
			//	put(dis);
            }
        }
    }
 //   put(dis);
    return dis[to];
}
int from1, from2, to, dis1[N], dis2[N], tx, ty;
vector<int>G[27];
int solve(){
    int ans1 = bfs(from1, to, dis1);
    if(ans1==-1)return -1;
  //  printf(" dis1 : %d\n", ans1);
    int ans2 = bfs(from2, to, dis2);
    if(ans2==-1)return -1;
 //   printf(" dis2 : %d\n", ans2);
    int ans = -1;
    for(int i = 0; i < 8; i++){
        int x = tx + step[i][0], y = ty + step[i][1], d = Hash(x,y);
        if('A'<=s[x][y]&&s[x][y]<='Z') d = G[s[x][y]-'A'][0];
        if(!inmap(x,y) || dis1[d]==-1 || dis2[d]==-1)continue;
        if(ans==-1 || ans > max(dis1[d], dis2[d]))
            ans = max(dis1[d], dis2[d]);
    }
    if(ans==-1)return -1;
    return ans+1;
}
int main() {
    while (~scanf("%d %d", &n, &m)) {
        init();
        for(int i = 1; i <= n; i++) {
            scanf("%s", s[i]+1);
            for(int j = 1; j <= m; j++)
                if(s[i][j]=='*')
                    to = Hash(i,j), tx = i, ty = j;
                else if(s[i][j]=='$')
                    from1 = Hash(i,j);
                else if(s[i][j]=='!')
                    from2 = Hash(i,j);
                else if('A'<=s[i][j]&&s[i][j]<='Z'){
                    if((int)G[s[i][j]-'A'].size()==0)
                    G[s[i][j]-'A'].push_back(Hash(i,j));
                }
        }
   //     printf("end:(%d,%d), to=%d, from1=%d, from2=%d\n",tx,ty,to,from1,from2);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
                if(inmap(i,j))
                for(int z = 0; z < 8; z++)
                {
                    int x = i+step[z][0], y = j+step[z][1];
                    if(!inmap(x,y))continue;
                    int u = Hash(i,j), v= Hash(x,y);
                    if('A'<=s[i][j]&&s[i][j]<='Z')u = G[s[i][j]-'A'][0];
                    if('A'<=s[x][y]&&s[x][y]<='Z')v = G[s[x][y]-'A'][0];
                    if(u!=v)
                    add(u,v,1);
                }
        int ans = solve();
        if(ans==-1)puts("Impossible");
        else printf("%d\n",ans);
        for(int i = 0; i < 26; i++)G[i].clear();
    }
    return 0;
}
/*
1 3
$*!

1 3
*!$
7 3
!#$
A#B
###
B#A
#C#
###
C.*

5 5
#A##$
#.*#A
#.B##
#####
!..B#


*/


 类似资料:

相关阅读

相关文章

相关问答