题目描述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;
}