题394.ABC272-D - Root M Leaper
一、题目
二、题解
本题限定跳到的下一个点到当前点的距离必须为sqrt(M),要求以(1,1)为源点到各个N*N点阵上各个点的步数。
对此,我们只需要利用距离约束确定跳点规则dx[],dy[],然后bfs求无权图单源最短路即可。
代码如下:
#include <bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<n;i++)
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int Inf=0x3f3f3f3f;
const int maxn=440,maxm=2e4+2;
int N,M;
int dx[maxn*maxn],dy[maxn*maxn],cnt;//类似于之前固定的往上下左右四个方向跳1步的const规则dx,dy,这里是要你根据sqrt(M)限制生成跳的规则
int dist[maxn][maxn];
void bfs()
{
memset(dist,Inf,sizeof dist);
queue<pii> q;
q.push({1,1});
dist[1][1]=0;
while(!q.empty())
{
pii t=q.front();
q.pop();
int x=t.x,y=t.y;
rep(i,0,cnt)
{
int xx=x+dx[i],yy=y+dy[i];
if(xx<=0||yy<=0||xx>N||yy>N) continue;
if(dist[xx][yy]>dist[x][y]+1)
{
dist[xx][yy]=dist[x][y]+1;
q.push({xx,yy});
}
}
}
}
int main()
{
scanf("%d%d",&N,&M);
rep(i,0,N+1)//生成dx,dy规则
{
rep(j,i,N+1)
{
if(i*i+j*j==M)//(0,0)作为中心点,向周围寻找能跳的规则点
{
dx[cnt]=i,dy[cnt]=j,cnt++;
dx[cnt]=i,dy[cnt]=-j,cnt++;
dx[cnt]=-i,dy[cnt]=j,cnt++;
dx[cnt]=-i,dy[cnt]=-j,cnt++;
dx[cnt]=j,dy[cnt]=i,cnt++;
dx[cnt]=j,dy[cnt]=-i,cnt++;
dx[cnt]=-j,dy[cnt]=i,cnt++;
dx[cnt]=-j,dy[cnt]=-i,cnt++;
}
}
}
bfs();//bfs求无权图单源最短路
rep(i,1,N+1)
{
rep(j,1,N+1)
{
if(dist[i][j]==Inf)
{
printf("-1 ");
}
else
{
printf("%d ",dist[i][j]);
}
}
putchar('\n');
}
}