G - 迷宫
最短路问题,两两建边,如果目标点为花那么边权为 1 − 1 = 0 1-1=0 1−1=0 ,否则为 1 1 1 固定源点与汇点,最短路的各种算法都可以写,这道题用双端队列比较好写,但是我用的是优先队列。
优先队列
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
const int N = 2010;
char g[N][N];
int f[N][N];
int n,m;
int dx[]={0,1,0,-1};
int dy[]={-1,0,1,0};
void bfs()
{
memset(f,0x3f,sizeof f);
f[1][1]=0;
priority_queue<PIII,vector<PIII>,greater<PIII> > Q;
Q.push({0,{1,1}});
while(Q.size())
{
PIII t=Q.top();Q.pop();
for(int i=0;i<4;i++)
{
int x=t.second.first+dx[i],y=t.second.second+dy[i];
if(x<1||x>n||y<1||y>m) continue;
if(g[x][y]=='#') continue;
if(f[x][y]!=0x3f3f3f3f) continue;
if(g[x][y]=='.') f[x][y]=min(f[x][y],f[t.second.first][t.second.second]+1);
if(g[x][y]=='*') f[x][y]=min(f[x][y],f[t.second.first][t.second.second]);
Q.push({f[x][y],{x,y}});
}
}
}
signed main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>(g[i]+1);
bfs();
if(f[n][m]>=0x3f3f3f3f/2) cout<<"-1"<<endl;
else cout<<f[n][m]<<endl;
return 0;
}
双端队列
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N = 2010;
char g[N][N];
int f[N][N];
int n,m;
int dx[]={0,1,0,-1};
int dy[]={-1,0,1,0};
void bfs()
{
memset(f,0x3f,sizeof f);
f[1][1]=0;
deque<PII> Q;
Q.push_front({1,1});
while(!Q.empty())
{
PII t=Q.front();Q.pop_front();
for(int i=0;i<4;i++)
{
int tx=t.first+dx[i],ty=t.second+dy[i];
if(tx<1||tx>n||ty<1||ty>m) continue;
if(g[tx][ty]=='#') continue;
int d=(g[tx][ty]=='.');
if(f[tx][ty]>f[t.first][t.second]+d)
{
f[tx][ty]=f[t.first][t.second]+d;
if(d==0) Q.push_front({tx,ty});
else Q.push_back({tx,ty});
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>(g[i]+1);
bfs();
if(f[n][m]>=0x3f3f3f3f/2) cout<<"-1"<<endl;
else cout<<f[n][m]<<endl;
return 0;
}