Logu-Horseのトラバース
出典:https://www.luogu.com.cn/problem/P1443
タイトル説明
n * m(1 <n、m <= 400)のチェス盤があり、特定の地点に馬がいて、馬がチェス盤の任意の地点に到達するために必要な最小歩数を計算する必要があります。
入力フォーマット
1行に4つのデータ、チェス盤のサイズと馬の座標
出力フォーマット
n * mマトリックス。これは、馬が特定のポイントに到達するために少なくとも数ステップを実行する必要があることを意味します(左に揃え、幅5グリッド、到達できない場合は出力-1)
サンプル
入る
3 3 1 1
**出力**
0 3 2
3 -1 1
2 1 4
タイトルを見て最初に思ったのは〜
1:馬はどうでしたか?ははははは。。。
「馬」歩行の方法は、各ステップで斜めに歩くことです。つまり、最初に1つの正方形を水平または真っ直ぐに歩き、次に斜めの線を斜めに歩きます。これは一般に「馬の歩行日」として知られています。図のように、「太陽」の対角線上の2点に一度に到達でき、他の場所に到達することはできません。
(X-2、y-1) | (X-2、y + 1) | |||
---|---|---|---|---|
(X-1、y-2) | (X-1、y + 2) | |||
(x、y)馬 | ||||
(X + 1、y-2) | (X + 1、y + 2) | |||
(X + 2、y-1) | (X + 2、y + 1) |
2:左揃え、幅5グリッド、Baiduはprintf( "%-5d"、a);を取得します。
3:次に、幅の最初の検索について考えて、最初にこの検索方法を説明しましょう。
例:このツリー
BFS検索、1から開始し、1に隣接する2、3、4をトラバースし、次に5 6 7 8 9 10から2、3、4までトラバースするとします(順序に注意してください)。
実装プロセスはキューを介して行われます:(ここでは、配列で表されるキュー)
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
ヘッドポインタがテールポインタと等しい場合、トラバーサルは完了しているか、条件を満たすポイントがトラバースされています。
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
各トラバーサルは元のポイント1から同じ距離にあることがわかります。したがって、最短パスの問題を実行するときに、bfsを考慮することができます。
最初にテンプレートがあります:
BFSテンプレート(幅の最初の検索)
void bfs()
{
初始化,初始状态存数组;
int head=0,tail=1,que[max_size];//构建队列
标记初始点
while(head<tail)
{
head++;//指向待扩展结点
for(i=1;i<=maxi;++i)
{
if(满足条件||不重复)
{
tail++;
将新节点存入队列
}
}
}
}
具体操作:
1:2次元配列res [] []を選択し、最初にすべての値-1を割り当て、最終結果(ボード上の各ポイントの最小ステップ数)を保存します
2:構造配列aを使用して馬の位置を表し、 BFSテンプレート、ヘッド、テールのキューとして機能し、キューのヘッドおよびテールポインターとして機能します。
3:2つの配列x []、y []は、馬が到達できる8つの位置を共同で表し、条件が満たされているかどうかを判断するために使用されます。次に、を判断するときに境界を越えないように注意してください。
それが来ると感じたら、それがACの場合は、最初に自分で試してみてください。
完全なコード:
#include<bits/stdc++.h>
int n,m,nx,ny;
int res[405][405];//res表示最终输出结果,下标代表棋盘位置,值代表最少步数
int x[8]={
1,2,-1,-2,-1,-2,1,2};
int y[8]={
2,1,2,1,-2,-1,-2,-1};
struct queue{
int x,y;
}a[40010];//构建bfs的队列(用数组表示)
void bfs(int i,int j)
{
int head=1,tail=2;
a[2].x=i,a[2].y=j;
res[i][j]=0;//初始位置的最少步数为0
while(head<tail)
{
head++;
for(int q=0;q<8;q++)
{
//(xx,yy)表示目前马走到的位置,还有。。。~~变量名真的好难取~~
int xx=a[head].x+x[q];
int yy=a[head].y+y[q];
if((res[xx][yy]==-1) && xx>=1 && xx<=n && yy>=1 && yy<=m)//判断是否走过,是否越界
{
tail++;
res[xx][yy]=res[a[head].x][a[head].y]+1;//最少步数加一
a[tail].x=xx;
a[tail].y=yy;
}
}
}
}
int main()
{
scanf("%d%d%d%d",&n,&m,&nx,&ny);
memset(res,-1,sizeof res);
bfs(nx,ny);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
printf("%-5d",res[i][j]);
}
printf("\n");
}
}
ご不明な点がございましたら、皆様のフレンドリーなコメントを歓迎します。