ybt1330 最少步数
时空限制 1000ms/64MB
【题目描述】
在各种棋中,棋子的走法总是一定的,如中国象棋中马走“日”。有一位小学生就想如果马能有两种走法将增加其趣味性,因此,他规定马既能按“日”走,也能如象一样走“田”字。他的同桌平时喜欢下围棋,知道这件事后觉得很有趣,就想试一试,在一个(100×100)的围棋盘上任选两点A、B,A点放上黑子,B点放上白子,代表两匹马。棋子可以按“日”字走,也可以按“田”字走,俩人一个走黑马,一个走白马。谁用最少的步数走到左上角坐标为(1,1)的点时,谁获胜。现在他请你帮忙,给你A、B两点的坐标,想知道两个位置到(1,1)点可能的最少步数。
【输入】
A、B两点的坐标。
【输出】
最少步数。
【输入样例】
12 16 18 10
【输出样例】
8 9
代码
法一:STL队列
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 105;
const int dx[] = {-2,-2,-1, 1, 2, 2, 2, 2, 1,-1,-2,-2},
dy[] = {-1,-2,-2,-2,-2,-1, 1, 2, 2, 2, 2, 1};
int g[N][N],x1,y1,x2,y2;
struct node{
int x,y,step;
node(){ }
node(int a,int b,int c):x(a),y(b),step(c){ }
};
queue<node> q;
void bfs(){
fill(g[0],g[0]+N*N,-1);
q.push(node(1,1,0)); //入队
g[1][1] = 0;
while (!q.empty()){ //从(1,1)走向(x1,y1)(x2,y2)
node k=q.front(); q.pop();
if (g[x1][y1]>=0 && g[x2][y2]>=0){ //两个点都走过
cout<<g[x1][y1]<<endl<<g[x2][y2]<<endl;
return;
}
for (int i=0; i<12; i++){
int x=k.x+dx[i],y=k.y+dy[i];
if (x>=1 && x<=100 && y>=1 && y<=100 && g[x][y]==-1){
q.push(node(x,y,k.step+1));
g[x][y] = k.step+1;
}
}
}
}
int main(){
cin>>x1>>y1>>x2>>y2;
bfs();
return 0;
}
法二:手动队列
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 105;
const int dx[] = {-2,-2,-1, 1, 2, 2, 2, 2, 1,-1,-2,-2},
dy[] = {-1,-2,-2,-2,-2,-1, 1, 2, 2, 2, 2, 1};
int g[N][N],que[N*N][3],head,tail,x1,y1,x2,y2;
void bfs(){
fill(g[0],g[0]+N*N,-1);
que[++tail][0]=0; que[tail][1]=1; que[tail][2]=1; //入队
g[1][1] = 0;
while (head<tail){ //从(1,1)走向(x1,y1)(x2,y2)
head++; //出队
if (g[x1][y1]>=0 && g[x2][y2]>=0){ //两个点都走过
cout<<g[x1][y1]<<endl<<g[x2][y2]<<endl;
return;
}
for (int i=0; i<12; i++){
int x=que[head][1]+dx[i],y=que[head][2]+dy[i];
if (x>=1 && x<=100 && y>=1 && y<=100 && g[x][y]==-1){
que[++tail][0] = g[x][y] = que[head][0]+1;
que[tail][1]=x; que[tail][2]=y;
}
}
}
}
int main(){
cin>>x1>>y1>>x2>>y2;
bfs();
return 0;
}