数字接龙——第十五届蓝桥杯(大学B组软件赛)

想要解决这道题,如果你知道深度优先搜索,你会更好解决;如果你不懂深度优先搜索,也可以往下看,我会讲得很清楚,如果哪里没有看懂,欢迎评论问问题,本题不管你什么时候问问题,我都会回答,为的就是大家能够没有算法基础也能搞懂这道题。

题目要求路线不能交叉,大家仔细想想,往什么方向走的时候会有交叉的可能?不错,就是往1,3,5,7方向走的时候,只有往这4个方向走,才会有交叉的可能。

我的代码尽量不浪费空间,虽然这里的数据量很小。为了让以后碰到数据量大的题仍然可以不超时,我建议不管你写题的时候数据量有多小, 都秉持尽量不要浪费空间的理念。不过我说的是尽量哈。

代码如下,注释写的很详细了,不懂欢迎评论询问!

#include<iostream>
#include<string>
#include<vector>
using namespace std;
//dfs是深度优先搜索的意思
void dfs(int x,int y,vector<vector<int>> &a,vector<vector<bool>>& b,int dep);
int n,k;
//path用来存储临时路径,res用来春促最终路径
string path,res;
int dx[8]={-1,-1,0,1,1,1,0,-1};
int dy[8]={0,1,1,1,0,-1,-1,-1};
//四维布尔数组用来判断交叉,如e[x1][y1][x2][y2]=true代表存在从(x1,y1)到(x2,y2)的路径,反之则不存在。
//这个四维数组的每一个维度根据N的范围,至多有10种可能,所以大小为10就够用了
bool e[10][10][10][10];
int main()
{
  cin >> n >> k;
  //创建一个动态二维数组,用来存储数字
  vector<vector<int>> a(n,vector<int>(n));
  for(int i=0;i<n;i++)
  {
    for(int j=0;j<n;j++)
    {
      cin >> a[i][j];

    }
  }
  //创建与a数组对应的动态二维布尔数组,用来标记已过访问过的位置
  vector<vector<bool>> b(n,vector<bool>(n));
  //传入(0,0)位置的坐标,两个二维数组,以及已搜索的点数1
  dfs(0,0,a,b,1);
  //经过搜索后,如果res不是空字符串,就输出,否则输出-1
  if(res.empty())
    cout << -1;
  else if(res.size()==n*n-1)
    cout << res;
  return 0;
}

void dfs(int x,int y,vector<vector<int>> &a,vector<vector<bool>>& b,int dep)
{
  //判断递归的边界条件,如果不设置这个边界,那下面的递归一旦进入,就会陷入循环永远不能结束
  if(dep==n*n&&x==n-1&&y==n-1)
  {
    res=path;
  }
  //标记(x,y)已经搜索过
  b[x][y]=true;
  //往八个方向搜索
  for(int i=0;i<8;i++)
  {
    //(xx,xy)表示(x,y)经过朝i方向走后达到的坐标.[xx]意思是[新x],[xy]意思是[新y];
    int xx=x+dx[i],xy=y+dy[i];
    //判断新坐标是否越界
    if(xx<0||xx>=n||xy<0||xy>=n)
      continue;
    //判断到达新坐标是否会出现交叉
    if(i%2!=0&&(e[xx][y][x][xy]||e[x][xy][xx][y]))
      continue;
    //判断新坐标是否搜索过
    if(b[xx][xy])
      continue;
    //判断是否满足顺序的序列
    if((a[x][y]+1==a[xx][xy])||(a[xx][xy]==0&&a[x][y]==k-1))
    {
    //一旦进入这个if语句,标记存在有从(x,y)到(xx,xy)的路径
	  e[x][y][xx][xy]=true;
    //存进这个行走方向
    path+=i+'0';
    //搜索以(xx,xy)为起点的下一个点。
    dfs(xx,xy,a,b,dep+1);

    //一旦执行下面四行代码,则代表正在回溯
    //若res不为空,说明已经找到合法路径,直接继续回溯上一层递归,不用管下面的代码了
    if(!res.empty())
	  return;
    //若res为空,说明上面那行dfs(xx,xy,a,b,dep+1)进入后没有找到合法的下一步
    //于是删除上面存入的i方向,因为这个方向走了之后,(xx,xy)找不到合法的又一个新点
    path.pop_back();
    //同时取消这个路径标记
    e[x][y][xx][xy]=false;}


  }
  //若八方向搜索都找不到合法的下一个点,取消访问过这个点的标记,
  //同时回溯此层的上一层递归(如果这是最外层递归,则res为空字符串,返回主函数输出-1)
  b[x][y]=false;
  return ;
}

创作不易,求你点个赞支持一下吧 !

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值