LintCode 1828: Lake Escape (双状态BFS好题)

在LakeEscape游戏中,玩家需操控角色Albert在冰湖上滑行,避开陷阱,救出小狗Kuna,并安全抵达岸边。游戏采用二维网格表示湖泊,0代表冰面,1代表雪堆,-1代表陷阱。玩家只能沿水平或垂直方向移动,碰到雪堆时才能停止滑行。此游戏考验玩家的策略规划能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1828. Lake Escape

Description

Albert is stranded on a frozen lake. He wants to know if he can make it back to shore. He is currently on a snowbank that gives him some traction, but once he steps the ice. he will slide in the same direction until he hits another snowbank. There are also treacherous holes in the ice that he must avoid.

As a cruel twist of fate, Albert's young pup, Kuna, is also stranded, but on a different snowbank. Can Albert reach his pup AND make it to shore?

Albert can only move horizontally and vertically. He makes it to shore by leaving the lake grid.

The input contains these parameters:

  • side_length: the length of a side of the lake (it's a square)
  • lake_grid: a 2D matrix representing the lake 0 = ice, 1 = snowbank, -1 = hole
  • albert_row: row of Alber'ts snowbank
  • albert_column: column of Albert's snowbank
  • kuna_row: row of Kuna's snowbank
  • kuna_column: column of Kuna's snowbank

 

It is guaranteed |albert\_row-kuna\_row|+|albert\_column- kuna\_column|>0∣albert_row−kuna_row∣+∣albert_column−kuna_column∣>0。

Have you met this question in a real interview?  Yes

Problem Correction

Example

Input:
7
[[0,0,0,0,0,0,0],[0,0,-1,0,0,0,0],[0,0,1,-1,0,-1,0],[-1,0,1,0,0,0,0],[0,1,1,0,0,1,0],[-1,0,-1,0,-1,0,0],[0,0,0,0,0,0,0]]
4
1
3
2
Output: true

Explanation:

As it seen in the picture. Yellow ceil is Albert's location and red ceil is Kuna's location. Albert can turn right to (4,2) and up to (3,2) then turn right to leave the lake grid.

图片

 

Challenge

Albert can't go to the shore and then find Kuna.

 

解法1:

这道题感觉比较难。我起初的想法是用2步BFS(第1步先找狗,第2步离开),但代码很冗长。后来看了标准答案发现用一次BFS就可用了,但要分2种状态(find dog or not)来处理。

注意:
1) visit数组为3维vector,第1维表示find dog or not,第2,3维分别代表map的x,y值。
2) queue也是3维,定义成pair中加pair。
3) 这题因为有个特殊条件就是一旦遇到冰面,可以就着原来方向一直滑下去,所以加了个
 for (int j = 0; j <= side_length; ++j) 
循环。如果里面遇到狗了当越界或遇到snow bank或hole就退出。注意如果找到狗了肯定也是在snow bank上面,可以同时更新2个状态并退出。
4) 退出来后就看现在是什么情况:
Case 1: 如果找到狗了又越界了就返回true。
Case 2: 如果没越界又遇到雪堆,则加入新节点,新节点的状态按find_dog_flag来处理。
还有其他状态如下,都属于不考虑的情况,继续循环即可。
Case 3: 越界了没找到狗
Case 4: 没越界又没碰到雪堆(snow bank),那就是掉到雪坑(snow hole)里了。
 

class Solution {
public:
    /**
     * @param side_length: the length of a side of the lake (it's a square)
     * @param lake_grid: a 2D matrix representing the lake 0= ice, 1= snowbank, -1= hole 
     * @param albert_row: row of Albert's snowbank
     * @param albert_column: column of Albert's snowbank 
     * @param kuna_row: row of Kuna's snowbank 
     * @param kuna_column: column of Kuna's snowbank
     * @return: a bool - whether Albert can escape
     */
    bool lakeEscape(int side_length, vector<vector<int>> &lake_grid, int albert_row, int albert_column, int kuna_row, int kuna_column) {
        vector<int> dx = {1, -1, 0, 0};
        vector<int> dy = {0, 0, 1, -1};
        queue<pair<int, pair<int, int>>> q; //find_dog, <x, y>
        q.push({0, {albert_row, albert_column}});
        vector<vector<vector<int>>> visit(2, vector<vector<int>>(side_length, vector<int>(side_length, 0)));
        
        bool find_dog_flag = false;
        while(!q.empty()) {
            auto curNode = q.front();
            q.pop();
            if (visit[curNode.first][curNode.second.first][curNode.second.second]) continue;
            visit[curNode.first][curNode.second.first][curNode.second.second] = 1;

            for (int i = 0; i < 4; ++i) {
             //   bool isHole = false;
                bool outBound = false;
                bool isSnowBank = false;

                int newX = curNode.second.first;
                int newY = curNode.second.second;
                
                //keep sliding
                for (int j = 0; j <= side_length; ++j) {
                    newX += dx[i];
                    newY += dy[i];
                    
                    if (!find_dog_flag) {
                        if (newX == kuna_row && newY == kuna_column) {
                            find_dog_flag = true;
                            isSnowBank = true;
                            break; //find dog and in snowbank
                        }
                    }

                    if (newX < 0 || newX >= side_length || newY < 0 || newY >= side_length) {
                        outBound = true;
                        break;
                    }
                    
                    if (lake_grid[newX][newY] == -1) {
               //         isHole = true;
                        break;
                    }
                    
                    if (lake_grid[newX][newY] == 1) {
                        isSnowBank = true;
                        break; //bump into snowbank
                    }
                }
                
                if (outBound) {
                    if (find_dog_flag ) return true;
                } else if (isSnowBank) {
                    q.push({find_dog_flag, {newX, newY}});
                }
            }
        }
        return false;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值