蓝桥杯 算法训练 跳马
题目描述
- 资源限制
时间限制:1.0s 内存限制:256.0MB
- 问题描述
一个8×8的棋盘上有一个马初始位置为(a,b),他想跳到(c,d),问是否可以?如果可以,最少要跳几步?
- 输入格式
一行四个数字a,b,c,d。
- 输出格式
如果跳不到,输出-1;否则输出最少跳到的步数。
- 样例输入
1 1 2 3
- 样例输出
1
- 数据规模和约定
0<a,b,c,d≤8且都是整数。
方案1 方案1 递归搜索,dfs
#include<iostream>
using namespace std;
int a, b;
int c, d;
int dx[8] = {1, 1, -1, -1, 2, 2, -2, -2};
int dy[8] = {2, -2, 2, -2, 1, -1, 1, -1};
int ans;
bool flag[8][8];
int f(int a, int b, int c, int d, bool flag[8][8]){
if(a<=0 || a>8 || b<=0 || b>8 || c<=0 || c>8 || d<=0 || d>8 || flag[a-1][b-1]==true){
return -1;
}
if(a==c&&b==d){
return 0;
}
flag[a-1][b-1] = true;
int temp, min=64;
for(int i=0; i<8; i++){
temp = f(a+dx[i], b+dy[i], c, d, flag);
if(temp != -1){
min = min>temp+1?temp+1:min;
}
}
if(min==64){
return -1;
}else{
flag[a-1][b-1] = false;
return min;
}
}
int main(){
cin>>a>>b>>c>>d;
cout<<f(a, b, c, d, flag)<<endl;
return 0;
}
//方案2 dfs 非递归 压栈
#include<iostream>
#include<stack>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
int a, b;
int c, d;
int dx[8] = {1, 1, -1, -1, 2, 2, -2, -2};
int dy[8] = {2, -2, 2, -2, 1, -1, 1, -1};
int ans[8][8];
string int2str(int a, int b, int c){
string ans;
while(c!=0){
ans += char(c%10+'0');
c/=10;
}
ans += '_';
while(b!=0){
ans += char(b%10+'0');
b/=10;
}
ans += '_';
while(a!=0){
ans += char(a%10+'0');
a/=10;
}
reverse(ans.begin(), ans.end());
return ans;
}
void str2int(string s, int ans[]){
int i=0;
string a, b, c;
while(s[i]!='_'){
a+=s[i];
i++;
}
i++;
while(s[i]!='_'){
b+=s[i];
i++;
}
i++;
while(i<s.length()){
c+=s[i];
i++;
}
i = 0;
while(i<a.length()){
ans[0]+=(a[i]-'0')*pow(10, a.length()-i-1);
i++;
}
i = 0;
while(i<b.length()){
ans[1]+=(b[i]-'0')*pow(10, b.length()-i-1);
i++;
}
i=0;
while(i<c.length()){
ans[2]+=(c[i]-'0')*pow(10, c.length()-i-1);
i++;
}
}
void f(int a, int b, int ans[8][8]){
for(int i=0; i<8; i++){
for(int j=0; j<8; j++){
ans[i][j] = 64;
}
}
stack<string> st;
st.push(int2str(a, b, 0));
while(st.size()>0){
int temp[3] = {0};
str2int(st.top(), temp);
st.pop();
a = temp[0];
b = temp[1];
ans[a-1][b-1] = min(ans[a-1][b-1], temp[2]);
for(int i=0; i<8; i++){
if(a+dx[i]>0 && a+dx[i]<=8 && b+dy[i]>0 && b+dy[i]<=8 && (temp[2]+1)<ans[a+dx[i]-1][b+dy[i]-1]){
st.push(int2str(a+dx[i], b+dy[i], temp[2]+1));
}
}
}
for(int i=0; i<8; i++){
for(int j=0; j<8; j++){
ans[i][j] = ans[i][j]==64?-1:ans[i][j];
}
}
}
int main(){
cin>>a>>b>>c>>d;
f(a, b, ans);
cout<<ans[c-1][d-1]<<endl;
return 0;
}
方案3 BFS 队列
#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
int a, b;
int c, d;
int dx[8] = {1, 1, -1, -1, 2, 2, -2, -2};
int dy[8] = {2, -2, 2, -2, 1, -1, 1, -1};
bool flag[8][8];
string int2str(int a, int b, int c){
string ans;
while(c!=0){
ans += char(c%10+'0');
c/=10;
}
ans += '_';
while(b!=0){
ans += char(b%10+'0');
b/=10;
}
ans += '_';
while(a!=0){
ans += char(a%10+'0');
a/=10;
}
reverse(ans.begin(), ans.end());
return ans;
}
void str2int(string s, int ans[]){
int i=0;
string a, b, c;
while(s[i]!='_'){
a+=s[i];
i++;
}
i++;
while(s[i]!='_'){
b+=s[i];
i++;
}
i++;
while(i<s.length()){
c+=s[i];
i++;
}
i = 0;
while(i<a.length()){
ans[0]+=(a[i]-'0')*pow(10, a.length()-i-1);
i++;
}
i = 0;
while(i<b.length()){
ans[1]+=(b[i]-'0')*pow(10, b.length()-i-1);
i++;
}
i=0;
while(i<c.length()){
ans[2]+=(c[i]-'0')*pow(10, c.length()-i-1);
i++;
}
}
int f(int a, int b, int c, int d, bool flag[8][8]){
queue<string> qu;
qu.push(int2str(a, b, 0));
while(qu.size()>0){
int temp[3] = {0};
str2int(qu.front(), temp);
qu.pop();
a = temp[0];
b = temp[1];
flag[a-1][b-1] = true;
if(a==c&&b==d){
return temp[2];
}
for(int i=0; i<8; i++){
if(a+dx[i]>0 && a+dx[i]<=8 && b+dy[i]>0 && b+dy[i]<=8 && !flag[a+dx[i]-1][b+dy[i]-1]){
qu.push(int2str(a+dx[i], b+dy[i], temp[2]+1));
}
}
}
return -1;
}
int main(){
cin>>a>>b>>c>>d;
cout<<f(a, b, c, d, flag)<<endl;
return 0;
}