DFS--poj 2488

http://poj.org/problem?id=2488

大致题意:给出一个p行q列的国际棋盘,马可以从任意一个格子开始走,问马能否不重复的走完所有的棋盘。如果可以,输出按字典序排列最小的路径。打印路径时,列用大写字母表示(A表示第一列),行用阿拉伯数字表示(从1开始),先输出列,再输出行。

分析:如果马可以不重复的走完所有的棋盘,那么它一定可以走到A1这个格子。所以我们只需从A1这个格子开始搜索,就能保证字典序是小的;除了这个条件,我们还要控制好马每次移动的方向,控制方向时保证字典序最小(即按照下图中格子的序号搜索)。控制好这两个条件,直接从A1开始深搜就行了。

 

 

#include <iostream>
#include <deque>
#include <cstring>
using namespace std;

int dir[8][2]={-1,-2,1,-2,-2,-1,2,-1,-2,1,2,1,-1,2,1,2};  //注意顺序
int vis[8][8];

int r,c;
bool Judge(int x,int y)
{
    if(vis[x][y]==0&&x>=0&&x<r&&y>=0&&y<c)
        return true;
    return false;
}

struct Node
{
    int x,y;
};
deque<Node> d;
void Print()
{
    Node t;
    cout<<"A1";
    while(!d.empty())
    {
        t=d.front();
        cout<<(char)(t.y+65)<<t.x+1;
        d.pop_front();
    }
    cout<<endl;
}

bool dfs(int x,int y)
{
    int i,j,tag=0;
    for(i=0;i<r;i++)
    {
        for(j=0;j<c;j++)
           if(vis[i][j]!=1) tag=1;
        if(tag==1) break;
    } 

    if(tag==0) return true;           //递归终止条件,表明所有全部访问过

    for(i=0;i<8;i++)
    {
        int row=x+dir[i][0],col=y+dir[i][1];
        if(Judge(row,col))
        {
            vis[row][col]=1;            //设为访问过
            if(dfs(row,col))
            {
                Node t;
                t.x=row;t.y=col;
                d.push_front(t);        //如果DFS成功,从终点倒退到起点,故应每次应插到队首
                return true;
            }
            else
            {
                vis[row][col]=0;       //DFS失败,重新设置成未访问
                d.clear();             //一旦DFS失败,就清空,而不是弹出一个队列元素
            }
        }
    }
    return false;                      //路径搜索失败

}

int main()
{
    int n,i;
    cin>>n;
    for(i=0;i<n;i++)
    {
        cin>>r>>c;
        vis[0][0]=1;
        cout<<"Scenario #"<<i+1<<":"<<endl;
        if(r==1&&c==1) cout<<"A1"<<endl;
        else if(dfs(0,0)==false)
            cout<<"impossible"<<endl;
        else Print();
        memset(vis,0,sizeof(vis));
        d.clear();
        if(i!=n-1)
        cout<<endl;
    }
    return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值