浑水摸鱼

题目传送门
没有想到这个题目竟然是远古abc的f题

赛中错误思路

首先他有k步的说法,所以我就记录一下上一步是什么方向走过来的吗。然后,就可以计算了。
但是问题是什么?
就是说每一步你是不能直接更改(我不确定可不可以取min,没试过),因为你bfs你要保证每一步是单调的,但是这样就是不单调了对吧。

那么正解是什么?

我们有一些点是重复计算了的。虽然如果这个点不合法是不可以走的,但是如果这一个方向上有一个点他已经走过了,而且步数比现在少,那也就是后面的点就不用走了。
为什么?
因为后面的点总归可以从这个点走过去,总归不会比现在这个点劣。

代码如下

#include<bits/stdc++.h>
using namespace std;

const int d[4][2]={
    {-1,0},{1,0},{0,-1},{0,1}
};
int n,m,k;
int xa,ya,xb,yb;

int main(){
    cin.tie(0)->sync_with_stdio(0);
    freopen("hun.in","r",stdin);
    freopen("hun.out","w",stdout);
    cin>>n>>m>>k;
    cin>>xa>>ya>>xb>>yb;
    vector<string> s(n);
    vector<vector<bool>> b(n+1,vector<bool>(m+1,0));
    vector<vector<int>> dist(n+1,vector<int>(m+1,1<<30));
    queue<pair<int,int>> q;
    for(int i=0;i<n;i++) cin>>s[i];
    xa--,ya--,xb--,yb--;
    q.push({xa,ya});
    b[xa][ya]=1;
    dist[xa][ya]=0;
    while(q.size()){
        int x=q.front().first,y=q.front().second;
        q.pop();
        for(int i=0;i<4;i++){
            for(int j=1;j<=k;j++){
                int xx=x+d[i][0]*j;
                int yy=y+d[i][1]*j;
                if(xx<0||yy<0||xx>=n||yy>=m||s[xx][yy]=='@') break;
                if(dist[xx][yy]<=dist[x][y]) break;
                if(b[xx][yy]) continue;
                q.push({xx,yy});
                b[xx][yy]=1;
                dist[xx][yy]=dist[x][y]+1;
            }
        }
    }
    if(dist[xb][yb]!=1<<30) cout<<dist[xb][yb]<<endl;
    else cout<<-1<<endl;
}
posted @ 2026-01-24 11:59  zhangruotian_Max  阅读(1)  评论(0)    收藏  举报