solution-p4442

提供一种最简单易懂,好写的做法。

发现 $n ,m \leq 500$

在不看题目难度的情况下,很容易想到直接bfs

简单思考,发现人物每次有以下移动方式:

第一种:直接朴素的往四周走,不用技能。

第二种:开两枪,然后朴素的走向其中一个传送门,使用它。

于是,我们就写完了。

复杂度 $O(n^3)$

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
inline void write(int x){if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0');}
#define put() putchar(' ')
#define endl puts("")
const int MAX = 1505;
char a[MAX][MAX];
int dir[MAX][MAX][4][2];
int dis[MAX][MAX];

const int dir2[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

struct node{
    int x, y, k;
};

node que[MAX * MAX];int  sizee, backk;

void solve(){
    int n = read(), m = read();
    int sx = 0, sy = 0, ex = 0, ey = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            cin>>a[i][j];
            if(a[i][j] == 'C')  sx = i, sy = j;
            if(a[i][j] == 'F')  ex = i, ey = j;
        }
    }
    memset(dir, -1, sizeof(dir));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            for(int k = 0; k < 4; k++)  dir[i][j][k][0] = dir[i][j][k][1] = -1;
            if(a[i][j] == '#')  continue;
            for(int k = 1; k <= n; k++){
                if(i - k > 0)   if(a[i-k][j] == '#' and dir[i][j][0][1] == -1)  dir[i][j][0][0] = -k+1, dir[i][j][0][1] = 0;
                if(i + k <= n)  if(a[i+k][j] == '#' and dir[i][j][1][1] == -1)  dir[i][j][1][0] = k-1, dir[i][j][1][1] = 0;   
            }
            for(int k = 1; k <= m; k++){
                if(j + k <= m)  if(a[i][j+k] == '#' and dir[i][j][2][0] == -1)  dir[i][j][2][1] = k-1, dir[i][j][2][0] = 0;
                if(j - k > 0)   if(a[i][j-k] == '#' and dir[i][j][3][0] == -1)  dir[i][j][3][1] = -k+1, dir[i][j][3][0] = 0;
            }
        }
    }
    // write(dir[2][9][3][0]), put(), write(dir[2][9][3][1]), endl;
    que[++sizee] = node{sx, sy, 0};
    backk = 1;
    for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) dis[i][j] = 1145141919810;
    dis[sx][sy] = 0;
    int ans = 1145141919810;
    while(backk <= sizee){
        int nx = que[backk].x, ny = que[backk].y, K = dis[nx][ny];
        // write(nx), put(), write(ny), put(), write(K), endl;
        backk++;
        if(nx == ex and ny == ey){
            ans = min(ans, K);
            continue;
        }
        // bool  
        int pre = 1145141919810;
        for(int i = 0; i < 4; i++)  pre = min(pre, max(abs(dir[nx][ny][i][0]), abs(dir[nx][ny][i][1])));
        pre ++;
        for(int i = 0; i < 4; i++){
            int dx = nx + dir[nx][ny][i][0], dy = ny + dir[nx][ny][i][1];
            if(dx < 1 or dx > n or dy < 1 or dy > m or a[dx][dy] == '#' or dis[dx][dy] <= K + pre or max(abs(dir[nx][ny][i][0]), abs(dir[nx][ny][i][1])) <= pre)    continue;
            que[++sizee] = node{dx, dy, K+pre};
            // if(dx == 2 and dy == 2)  write(nx), put(), write(ny), endl;
            dis[dx][dy] = K + pre; 
        }
        for(int i = 0; i < 4; i++){
            int dx = nx + dir2[i][0], dy = ny + dir2[i][1];
            if(dx < 1 or dx > n or dy < 1 or dy > m or a[dx][dy] == '#' or dis[dx][dy] <= K + 1)    continue;
            que[++sizee] = node{dx, dy, K+1};
            dis[dx][dy] =  K + 1;
        }

    }
    if(ans == 1145141919810)    puts("nemoguce");
    else write(ans), endl;
}

signed main(){
    int t = 1;
    while(t--)  solve();
    return 0;
}
posted @ 2023-03-04 16:01  WRuperD  阅读(11)  评论(0编辑  收藏  举报  来源

本文作者:DIVMonster

本文链接:https://www.cnblogs.com/guangzan/p/12886111.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

这是一条自定义内容

这是一条自定义内容