POJ2488题解

poj2488题解

题意

骑士(类似于中国象棋里的马)从任意起点出发,遍历n*m的棋盘上的每一个格子,在任意终点结束,输出最小字典序遍历道路。

笺释

按照字典序遍历起点,然后进入dfs搜索。
按照下列1-8的顺序移动就是最小字典序

int movm[9]={0,-2,-2,-1,-1,1,1,2,2};
int movn[9]={0,-1,1,-2,2,-2,2,-1,1};

也就是按照向左上,左下,右上,右下移动。
记录路径用一个maps[num(当前步数)]数组即可,不用写递归记录。
本来半个小时就写完了,但是WA了很久,自己一直找不到错,取discuss里拿到了所有有效数据和AC代码对拍也都没错,最后发现是在遍历起点的代码

 for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                memset(maps,0,sizeof(maps));
                memset(vis,0,sizeof(vis));
                maps[1][0]=j;
                maps[1][1]=i;
                vis[j][i]=1;
                dfs(j,i,1);
                if(flag==1)
                {
                    break;
                }
            }
            if(flag==1)
                {
                    break;
                }
        }

dfs(j,i,1)一直写成了dfs(i,j,1),但是一般来说起点都是A1所以这里是能过很多样例的(我感觉是全部有效数据),不知道poj用什么样例卡掉的,不过很厉害。

完整代码

#include<cstdio>
#include<cstring>
#define MAXN 28
using namespace std;
int movm[9]={0,-2,-2,-1,-1,1,1,2,2};
int movn[9]={0,-1,1,-2,2,-2,2,-1,1};
int vis[MAXN][MAXN];
int maps[MAXN*MAXN][2];
int flag;
char alp[27]={'\0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
int n,m;
int t;
void print()
{
    for(int i=1;i<=n*m;i++)
    {
        printf("%c%d",alp[maps[i][1]],maps[i][0]);
    }
    printf("\n");
    printf("\n");

}
bool legal(int newn,int newm)
{
    if(!(newn>=1&&newn<=n))
    {
        return false;
    }
    if(!(newm>=1&&newm<=m))
    {
        return false;
    }
    return true;
}
void dfs(int temn,int temm,int num)
{
    if(num==n*m)
    {
        flag=1;
        print();
        return;
    }
    for(int i=1;i<=8;i++)
    {
        int newn=temn+movn[i];
        int newm=temm+movm[i];
        if(legal(newn,newm))
        {
        if(!vis[newn][newm])
        {
            vis[newn][newm]=1;
            maps[num+1][0]=newn;
            maps[num+1][1]=newm;
            dfs(newn,newm,num+1);
            if(flag)
            {
                return;
            }
            vis[newn][newm]=0;
            maps[num+1][0]=0;
            maps[num+1][1]=0;
        }
        }
    }
}
int main()
{
    //freopen("c:\\output.txt","w",stdout);
    int c=1;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&n,&m);
        printf("Scenario #%d:\n",c++);
        flag=0;
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                memset(maps,0,sizeof(maps));
                memset(vis,0,sizeof(vis));
                maps[1][0]=j;
                maps[1][1]=i;
                vis[j][i]=1;
                dfs(j,i,1);
                if(flag==1)
                {
                    break;
                }
            }
            if(flag==1)
                {
                    break;
                }
        }
        if(n*m>26)
        {
            flag=0;
        }
        if(flag==0)
        {
            printf("impossible\n");
            printf("\n");
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值