CSUOJ1224 BFS模板加实例 ACM小组的古怪象棋

问题描述

Description
只有一个马了,又只剩下一个将,两个棋子都在棋盘的一边,马不能出这一半棋盘的范围,棋盘的大小(n行m列)。想知道他的马最少需要跳几次才能吃掉将(我们假定其不会移动)。
Input
每组数据一行,分别为六个用空格分隔开的正整数n,m,x1,y1,x2,y2分别代表棋盘的大小n,m,以及将的坐标和马的坐标。(1<=x1,x2<=n<=20,1<=y1,y2<=m<=20,将和马的坐标不相同)
Output
输出对应也有若干行,请输出最少的移动步数,如果不能吃掉将则输出“-1”(不包括引号)。
Sample Input
8 8 5 1 4 5
Sample Output
3

我的思路

本题特色: 马的行走方式 防止蹩脚 用了四个 if 解决
这题是学习BFS的基础题 类似于搜索迷宫 只是把棋子换成了马 跳转方式不一样 本题同样可以适用DP方法解决 所以 对于初学者 建议先学习BFS解法 再经过少量改动达到DP的方法 系统的学习ACM算法

[AC代码]

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cmath>
#define LL long long
#define fi first
#define se second
#define IO; std::ios::sync_with_stdio(false);std::cin.tie(0);
//降低输入输出时间
using namespace std;

const int N = 2e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-10;
const double PI = acos(-1);

/**********BFS模板**********/
const int maxn=100;
bool vst[maxn][maxn]; // 访问标记
int t[maxn][maxn];//存放最小层数
int dir[8][2]={{2,1},{2,-1},{-2,1},{-2,-1},{1,2},{-1,2},{1,-2},{-1,-2}}; // 方向向量
int res;//结果层数
int n,m,xm,ym,xj,yj;//输入量
struct State // BFS 队列中的状态数据结构
{
    int x,y; // 坐标位置
    int Step_Counter; // 搜索步数统计器
};

State a[maxn];

bool CheckState(State s) // 约束条件检验
{
    if(vst[s.x][s.y]==0 && s.x>=0 && s.x<n && s.y>=0 && s.y<m) // 满足条件
        return 1;
    else
        return 0;
}

void bfs(State st)
{
    memset(vst,0,sizeof(vst));
    queue <State> q; // BFS 队列
    State now,next; // 定义2 个状态,当前和下一个
    st.Step_Counter=0; // 计数器清零
    q.push(st); // 入队
    vst[st.x][st.y]=1; // 访问标记
    while(!q.empty())
        {
        now=q.front(); // 取队首元素进行扩展
        if(now.x==xj&&now.y==yj) // 出现目标态,此时为Step_Counter 的最小值,可以退出即可
        {
            res=now.Step_Counter;// 结果
            return;
        }
        for(int i=0;i<8;i++)
        {

            next.x=now.x+dir[i][0]; // 按照规则生成下一个状态
            next.y=now.y+dir[i][1];
            next.Step_Counter=now.Step_Counter+1; // 计数器加1
            //防止蹩脚
            if(dir[i][0]==2  &&  now.x+1==xj  &&  now.y==yj  ) continue;
            if(dir[i][0]==-2 &&  now.x-1==xj  &&  now.y==yj  ) continue;
            if(dir[i][1]==2  &&  now.x==xj    &&  now.y+1==yj) continue;
            if(dir[i][1]==-2 &&  now.x==xj    &&  now.y-1==yj) continue;
            if(CheckState(next)) // 如果状态满足约束条件则入队
            {
            t[next.x][next.y]=min(t[next.x][next.y],t[now.x][now.y]+1);
            q.push(next);
            vst[next.x][next.y]=1; //访问标记
            }
            }
        q.pop(); // 队首元素出队
        }
    return;
}

void csh()
{
    for(int i=0;i<100;i++)
        for(int j=0;j<100;j++)
            t[i][j]=inf;
}
int main()
{
    IO;
    while(cin>>n>>m>>xj>>yj>>xm>>ym)
    {
        csh();
        xj--,yj--,xm--,ym--;
        t[xm][ym]=0;
        State st;
        st.x=xm;st.y=ym;
        bfs(st);
        if (t[xj][yj]==inf) cout<<"-1"<<endl;
         else cout<<res<<endl;//或者cout<<t[xj][yj]<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyuhang99/article/details/81429033