洛谷 马 的遍历

本文探讨了一个经典的算法问题——马走棋盘,目标是最少步数从指定位置到达棋盘上的任意一点。通过对比两种不同的实现方式,一种使用循环和数组结合的方法,另一种采用队列和深度优先搜索策略,详细解析了如何高效地解决该问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述problem
有一个n*m的棋盘(1<n,m<=400),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步

输入输出格式
输入格式:
一行四个数据,棋盘的大小和马的坐标

输出格式:
一个n*m的矩阵,代表马到达某个点最少要走几步(左对齐,宽5格,不能到达则输出-1)

输入输出样例
输入样例#1: 复制
3 3 1 1
输出样例#1: 复制
0 3 2
3 -1 1
2 1 4

感觉用循环 结合数组 的方法遍历有效好多 ;
刚开始的时候用了 8 个IF语句判断 结果就是不对一百多行看的眼都花了,还是没有发现错的地方 ?
对了 左对齐 要输出 %-5d ~
下面是AC

#include<cstdio>
#include<queue>
using namespace std;
int vis[410][410],ans[410][410];
int m,n,sx,sy;
struct node{
	int x;
	int y;
	int step;
};
int check (int x,int y){
	if(x<1||x>m||y<1||y>n||vis[x][y]) return 0;
	return 1;
}
int main(){
	//next 枚举八个方向 
	int sum=1;int next[8][2]={{1,2},{2,1},{1,-2},{-2,1},{-1,-2},{-2,-1},{-1,2},{2,-1}};
	scanf("%d%d%d%d",&m,&n,&sx,&sy);
	queue<node> q;
	node w;
	w.x =sx;
	w.y =sy;
	w.step =0;
	vis[sx][sy]=1;
	ans[sx][sy]=0;
	q.push(w);
	while(!q.empty() ){
		node f,k;
		f=q.front() ;
		q.pop() ;
		for(int i=0;i<8;i++){
				if(check(f.x +next[i][0],f.y +next[i][1])) {
			k.x =f.x +next[i][0];
			k.y =f.y +next[i][1];
			k.step =f.step +1;
			q.push(k); 
			vis[k.x][k.y ]=1;
			ans[k.x ][k.y]=k.step ;
			sum++;
		}
		}
	if(sum==m*n) break; 
		
	} 
	int i,j;
	

		for(i=1;i<=m;i++){
		for(j=1;j<=n;j++){
			if(ans[i][j]==0&&(i!=sx||j!=sy)) printf("%-5d",-1);
			else printf("%-5d",ans[i][j]);
		}
		printf("\n");
	}
	
	
	
}

下面是我还找不到为什么错的代码 ~

#include<cstdio>
#include<queue>
using namespace std;
int vis[410][410],ans[410][410];
int m,n,sx,sy;
struct node{
	int x;
	int y;
	int step;
};
int check (int x,int y){
	if(x<1||x>m||y<1||y>n||vis[x][y]) return 0;
	return 1;
}
int main(){
	int sum=1;
	scanf("%d%d%d%d",&m,&n,&sx,&sy);
	queue<node> q;
	node w;
	w.x =sx;
	w.y =sy;
	w.step =0;
	vis[sx][sy]=1;
	ans[sx][sy]=0;
	q.push(w);
	while(!q.empty() ){
		node f,k;
		f=q.front() ;
		q.pop() ;
		if(check(f.x +1,f.y +2)) {
			k.x =f.x+1;
			k.y =f.y +2;
			k.step =f.step +1;
			q.push(k); 
			vis[k.x][k.y ]=1;
			ans[k.x ][k.y]=k.step ;
			sum++;
		}
		if(check(f.x +2,f.y +1)) {
			k.x =f.x+2;
			k.y =f.y +1;
			vis[f.x +2][f.y+1]=1;
			k.step =f.step +1;
			q.push(k); 
			vis[k.x][k.y ]=1;
			ans[k.x ][k.y]=k.step ;
			sum++;
		}
		if(check(f.x -1,f.y +2)) {
			k.x =f.x-1;
			k.y =f.y +2;
			k.step =f.step +1;
			q.push(k); 
			vis[k.x][k.y ]=1;
			ans[k.x ][k.y]=k.step ;
			sum++;
		}
			if(check(f.x +2,f.y -1)) {
			k.x =f.x+2;
			k.y =f.y-1;
			k.step =f.step +1;
			q.push(k); 
			vis[k.x][k.y ]=1;
			ans[k.x ][k.y]=k.step ;
			sum++;
		}
		if(check(f.x -1,f.y -2)) {
			k.x =f.x-1;
			k.y =f.y -2;
			k.step =f.step +1;
			q.push(k); 
			vis[k.x][k.y ]=1;
			ans[k.x ][k.y]=k.step ;
			sum++;
		}
		if(check(f.x -2,f.y -1)) {
			k.x =f.x-2;
			k.y =f.y -1;
			k.step =f.step +1;
			q.push(k); 
			vis[k.x][k.y ]=1;
			ans[k.x ][k.y]=k.step ;
			sum++;
		}
		if(check(f.x +1,f.y -2)) {
			k.x =f.x+1;
			k.y =f.y -2;
			k.step =f.step +1;
			q.push(k); 
			vis[k.x][k.y ]=1;
			ans[k.x ][k.y]=k.step ;
			sum++;
		}
		if(check(f.x +2,f.y -1)) {
			k.x =f.x+2;
			k.y =f.y -1;
			k.step =f.step +1;
				q.push(k); 
			vis[k.x][k.y ]=1;
			ans[k.x ][k.y]=k.step ;
			sum++;
		}
		if(sum==m*n) break;
	} 
	int i,j;
	

		for(i=1;i<=m;i++){
		for(j=1;j<=n;j++){
			if(ans[i][j]==0&&(i!=sx||j!=sy)) printf("%-5d",-1);
			else printf("%-5d",ans[i][j]);
		}
		printf("\n");
	}
	
	
	
}

From 某大佬
感觉中间的这个很妙(ans []还实现了book[]一样的标记作用
不过首先还是要遍历一遍把所有的ans[]值设为inf 即无穷大~

if (ans[x + xx[i]][y + yy[i]] > ans[x][y] + 1)
				{
					ans[x + xx[i]][y + yy[i]] = ans[x][y] + 1;
					++r; X[r] = x + xx[i], Y[r] = y + yy[i]; 
				}

全部是这样的····

#include <cstdio>
#define FOR(i, l, r) for(int i = l; i <= r; ++i)


using namespace std;

const int inf = 10000000;
const int xx[8] = {-2, -2, -1, -1, 1, 1, 2, 2};
const int yy[8] = {1, -1, 2, -2, 2, -2, 1, -1};

int ans[410][410];
int X[410 * 410], Y[410 * 410];
int n, m, x, y;

int main()
{
	scanf("%d%d%d%d", &n, &m, &x, &y);
	FOR(i, 1, n) FOR(j, 1, m) ans[i][j] = inf;
	int l = 1, r = 1;
	X[1] = x, Y[1] = y; ans[x][y] = 0;
	while (l <= r)
	{
		x = X[l]; y = Y[l++];
		FOR(i, 0, 7)
			if (x + xx[i] >= 1 && x + xx[i] <= n && y + yy[i] >= 1 && y + yy[i] <= m)
				if (ans[x + xx[i]][y + yy[i]] > ans[x][y] + 1)
				{
					ans[x + xx[i]][y + yy[i]] = ans[x][y] + 1;
					++r; X[r] = x + xx[i], Y[r] = y + yy[i]; 
				}
	}
	FOR(i, 1, n)
	{
		FOR(j, 1, m)
			printf("%-5d", ans[i][j] == inf ? -1 : ans[i][j]);
		puts("");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值