zoukankan      html  css  js  c++  java
  • 跳马(广搜_队列)

    时限:1000ms 内存限制:10000K 总时限:3000ms

    描述:

    在国际象棋中,马的走法与中车象棋类似,即俗话说的“马走日”,下图所示即国际象棋中马(K)在一步能到达的格子(其中黑色的格子是能到达的位置)。

    现有一200*200大小的国际象棋棋盘,棋盘中仅有一个马,给定马的当前位置(S)和目标位置(T),求出马最少需要多少跳才能从当前位置到达目标位置。

    输入:

    本题包含多个测例。输入数据的第一行有一个整数N(1<=N<=1000),表示测例的个数,接下来的每一行有四个以空格分隔的整数,分别表示马当前位置及目标位置的横、纵坐标C(x,y)和G(x,y)。坐标由1开始。

    输出:

    对于每个测例,在单独的一行内输出一个整数,即马从当前位置跳到目标位置最少的跳数。

    输入样例:

    2

    1 1 2 1

    1 5 5 1

    输出样例:

    3

    4

    #include<stdio.h>
    #define n 200
    char a[200][200]={0};//迷宫数组(坐标由0开始)
    int open[2000],openlen=2000,head,tail;
    int Berow,Becol;//起点横纵坐标
    int Enrow,Encol;//终点横,纵坐标
    
    void init();
    int search();
    int emptyopen();
    int takeoutopen();
    int canmoveto(int row,int col,int *p,int *q,int i);//i代表跳马的方向
    int isaim(int row,int col);
    int used(int row,int col);
    void addtoopen(int row,int col);
    /////////////////////////////////////////////////////////////////////////
    int main()
    {
        int m;
        scanf("%d",&m);//m个测例
        for(int i=0;i<m;i++)
        {
            init();
            int temp=search();//若目标节点不可达,则会返回0
            printf("%d\n",temp);
        }    
        return 0;
    }
    void init()//初始化工作
    {
        scanf("%d%d%d%d",&Berow,&Becol,&Enrow,&Encol);//起始点坐标(从1开始的)
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                a[i][j]=0;//棋盘初始化                
        head=0; tail=1;
        open[0]=(Berow-1)*n+Becol-1;//队列初始化
    }
    ///////////////////////////////////////////////////////////////////
    int search()//寻找最短步长
    {
        int row,col;
        int u,r,c,num=0;
        while(!emptyopen())
        {
            u=takeoutopen();
            row=u/n;  col=u%n;
            num=a[row][col];
            for(int i=0;i<8;i++)//八个方向跳马
            {
                if(canmoveto(row,col,&r,&c,i))
                {
                    if(isaim(r,c))//到达终点                
                        return(num+1);//返回最短步长                
                    else if(!used(r,c))//没到达终点且未走到过
                    {
                        a[r][c]=num+1;//标记走过的点
                        addtoopen(r,c);
                    }
                }
            }
        }
        return 0;//全盘搜索后,还是没有找到通路
    }
    int emptyopen()//判断队列是否为空
    {
        if(head==tail)
            return 1;
        return 0;
    }
    int takeoutopen()//取对列头结点
    {
        int u;
        u=open[head++];
        head=head%openlen;
        return u;
    }
    int canmoveto(int row,int col,int *p,int *q,int i)//i代表跳马的方向
    {
        switch(i)
        {
            case 1: row+=2; col--;   break;//左下1    
            case 2: row++;  col-=2;  break;//左下2    
            case 3: row--;  col-=2;  break;//左上1
            case 4: row-=2; col--;   break;//左上2 
            case 5: row-=2; col++;   break;//右上1
            case 6: row--;  col+=2;  break;//右上2
            case 7: row++;  col+=2;  break;//右下1
            case 8: row+=2; col++;   break;//右下2    
        }
        *p=row;
        *q=col;
        if(row>=0 &&col>=0 &&row<n &&col<n &&a[row][col]==0)
            return 1;
        return 0;
    }
    int isaim(int row,int col)//判断是否到达终点
    {
        if(row==Enrow-1 &&col==Encol-1)
            return 1;
        return 0;
    }
    int used(int row,int col)
    {
        if(a[row][col]==0)
            return 0;
        return 1;
    }
    void addtoopen(int row,int col)//新结点加入队列
    {
        int u=row*n+col;
        open[tail++]=u;
        tail=tail%openlen;
    }
  • 相关阅读:
    留言板!
    NX二次开发-OLE/COM向EXCEL表格中插入图片
    NX二次开发-UFUN读取图纸尺寸的值UF_DRF_ask_dimension_text
    NX二次开发-UFUN修剪体UF_MODL_trim_body
    NX二次开发-UFUN相加布尔操作,可保留或删除目标体,工具体UF_MODL_unite_bodies_with_retained_options
    C++之判断字符串是否是数字
    CommandLineToArgvW调EXE传入参数【转载】
    NX二次开发-用户自定义资源栏选项卡RegisterActivationCallback
    NX二次开发-自定义添加右键菜单RegisterConfigureContextMenuCallback
    NX二次开发-调系统命令UF_load_library[UFUN调DLL]
  • 原文地址:https://www.cnblogs.com/IThaitian/p/2593374.html
Copyright © 2011-2022 走看看