算法题解1

题目:

给定一个二维数组,数字表示海拔高度,输入起始点和终点,判断从起始点能否达到终点?

条件:

1. 搜寻过程,每次只能移动一步,步长为1,且海拔为0的点才能作为搜寻经过的路线

2. 搜寻过程中,直角拐弯(90度)次数不能超过K次, K=2

例子:

矩阵matrix=[

[1 0 5 5] 

[3 0 0 3]

[5 7 0 1]

]

起点:(0,0), 终点:(2,3)

输出:

  No

 

解题思路:

(1)路径搜索,用回溯算法,必须定义访问数组vis

(2)搜寻方向:水平方向和竖直方向

(3)搜寻出现拐弯的条件:上次搜寻方向和这次搜寻方向不在一个方向即可:

            水平+竖直,或竖直+水平

     定义一个int型标记pre_dir,-1代表水平方向,0代表初始时,1代表竖直方向,它代表上次搜寻方向,与当前搜寻方向now_dir比较:

     情况1:pre_dir和now_dir在同一方向,不用拐弯

     情况2:pre_dir和now_dir在不同方向,拐弯,统计++

     情况2:pre_dir = 0时,表示刚开始搜索,不用拐弯

代码如下:

/*  
*  CPlusPlus online programming website: http://cpp.sh/
*/

#include <iostream>
#include <vector>
using namespace std;

//定义拐弯(90度)处数限制,不超过K次
#define K 2

//用来统计<pre, now, next> 三种连续位置的拐弯次数,分三种情况
int helper(int pre_dir, int now_dir, int cnt) {
    int val = pre_dir * now_dir;
//情况1
    if (val > 0) //说明上次和这次在相同方向,如只沿着水平方向移动(或竖直方向),此时没有直角拐弯,而是在同一条线上搜寻
      return cnt;   

  //情况2:
    if (val < 0) //说明上次和这次在不同方向,此时发生新的直角拐弯, 统计++
       return cnt + 1;
    
  //情况3:
    return cnt;
}

bool CanCross(vector<vector<int>> const& matrx,  int x0, int y0, int x, int y, int xx, int yy, vector<vector<int>>& vis, int pre_dir, int cnt) {
    if (x == xx && y == yy && cnt <= K) return true; //到达终点且拐歪次数没超
    
    if (x < 0 || x >= matrx.size() || y < 0 || y >= matrx[0].size() || vis[x][y] ||   matrx[x][y] && !((x0 == x) && (y0 == y)) || cnt > K ) {
      //cout << endl << x << "," << y << "  InValid!\n";
      return false;
    }
      
     vis[x][y]  = 1; //回溯数组处理
     if (CanCross(matrx, x0, y0, x-1, y, xx, yy, vis, -1, helper(pre_dir, -1,cnt)) || 
         CanCross(matrx, x0, y0, x+1, y, xx, yy, vis, -1, helper(pre_dir, -1,cnt)) ||
         CanCross(matrx, x0, y0, x, y+1, xx, yy, vis, 1,  helper(pre_dir, 1,cnt)) ||
         CanCross(matrx, x0, y0, x, y-1, xx, yy, vis, 1,  helper(pre_dir, 1,cnt)))
       return true;
       
     vis[x][y]  = 0; 回溯数组复原
     return false; 
}

int main()
{
  vector<vector<int>> matrix = {
      {1,0,5,5},
      {3,0,0,3},
      {5,7,0,1}
   };
   
   /*for (auto r : matrix) {
      for (auto l : r)
       cout << l << " ";
       cout << endl;
   }*/
   
   int x0 = 0;
   int y0 = 0;
   int x1 = 2;
   int y1 = 3;
   if (matrix[x0][y0] != matrix[x1][y1]) {
       cout << "No";
   } else {
       vector<vector<int>> vis(matrix.size(), vector<int>(matrix[0].size(), 0));
        
       if (CanCross(matrix, x0, y0,  x0, y0, x1, y1,vis, 0, 0))
         cout << "YES";
       else
         cout << "No";
   }
   return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Poo_Chai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值