题目大意:棋盘,跳马步,格子上有水,莲花,石头,有水的地方可以+莲花,给定起点终点,求+多少莲花才能到达终点,并求在此前提下的步数和方案数
题解:三个要求优先级不同,大力if,只有在优先级高的要求相同时才更新优先级低的
我的收获:多条件最短路
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define pii pair<int,int>
#define mp(x,y) make_pair(x,y)
const int M=35;
#define INF 0x3f3f3f3f
const int dx[]={-2,-1,1,2,2,1,-1,-2};
const int dy[]={-1,-2,-2,-1,1,2,2,1};
int n,m;
int stx,sty,edx,edy;
int mp[M][M],step[M][M],add[M][M];
long long cnt[M][M];
bool vis[M][M];
queue<pii> q;
inline bool out(int x,int y){return x>n||x<1||y>m||y<1;}
void bfs(int x,int y)
{
memset(add,0x3f,sizeof(add));add[x][y]=0;
memset(step,0x3f,sizeof(step));step[x][y]=0;
memset(vis,0,sizeof(vis));vis[x][y]=1;
memset(cnt,0,sizeof(cnt));cnt[x][y]=1;
q.push(mp(x,y));
while(!q.empty())
{
pii u=q.front();q.pop();
int nx=u.first,ny=u.second;vis[nx][ny]=0;
for(int k=0;k<8;k++){
int fx=nx+dx[k],fy=ny+dy[k];
if(out(fx,fy)||mp[fx][fy]==2) continue;
int len=mp[fx][fy]==0;
if(add[fx][fy]>add[nx][ny]+len){
add[fx][fy]=add[nx][ny]+len;
step[fx][fy]=step[nx][ny]+1;
cnt[fx][fy]=cnt[nx][ny];
if(!vis[fx][fy]) vis[fx][fy]=1,q.push(mp(fx,fy));
}
else if(add[fx][fy]==add[nx][ny]+len){
if(step[fx][fy]>step[nx][ny]+1)
{
step[fx][fy]=step[nx][ny]+1;
cnt[fx][fy]=cnt[nx][ny];
if(!vis[fx][fy]) vis[fx][fy]=1,q.push(mp(fx,fy));
}
else if(step[fx][fy]==step[nx][ny]+1){
cnt[fx][fy]+=cnt[nx][ny];
if(!vis[fx][fy]) vis[fx][fy]=1,q.push(mp(fx,fy));
}
}
}
}
}
void work()
{
bfs(stx,sty);
if(add[edx][edy]==INF){puts("-1");return ;}
printf("%d\n%d\n%lld\n",add[edx][edy],step[edx][edy],cnt[edx][edy]);
}
void init()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&mp[i][j]);
if(mp[i][j]==3) stx=i,sty=j;
if(mp[i][j]==4) edx=i,edy=j;
}
}
int main()
{
init();
work();
return 0;
}