"""
DFS算法实现
深度优先搜索算法，不保证找到最短路径，但可能更快找到任意路径
"""

from collections import deque
from typing import List, Tuple, Optional, Dict, Set

class DFS:
    """
    DFS算法实现
    深度优先搜索算法，不保证找到最短路径，但可能更快找到任意路径
    """
    
    def __init__(self):
        """初始化DFS算法"""
        self.depth_limit = 1000  # 深度限制，防止无限递归
        self.stats = {
            'nodes_visited': 0,
            'max_depth': 0
        }
        
    def find_path(self, grid: List[List[int]], start: Tuple[int, int], goal: Tuple[int, int]) -> Optional[List[Tuple[int, int]]]:
        """
        使用DFS算法查找路径
        
        Args:
            grid: 网格地图，0表示可通行，1表示障碍物
            start: 起点坐标 (row, col)
            goal: 终点坐标 (row, col)
            
        Returns:
            路径坐标列表，如果找不到路径则返回None
        """
        # 重置统计信息
        self.stats = {
            'nodes_visited': 0,
            'max_depth': 0
        }
        
        # 获取网格尺寸
        rows = len(grid)
        cols = len(grid[0]) if rows > 0 else 0
        
        # 检查起点和终点是否有效
        if not (0 <= start[0] < rows and 0 <= start[1] < cols):
            return None
        if not (0 <= goal[0] < rows and 0 <= goal[1] < cols):
            return None
        if grid[start[0]][start[1]] == 1 or grid[goal[0]][goal[1]] == 1:
            return None
            
        # 初始化栈
        stack = [(start, 0)]  # (节点, 深度)
        
        # 初始化父节点字典和访问集合
        parent: Dict[Tuple[int, int], Tuple[int, int]] = {}
        visited: Set[Tuple[int, int]] = {start}
        
        # 4方向移动（上下左右）
        directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
        
        while stack:
            # 更新统计信息
            self.stats['nodes_visited'] += 1
            
            # 取出栈顶节点
            current, depth = stack.pop()
            self.stats['max_depth'] = max(self.stats['max_depth'], depth)
            
            # 如果超过深度限制，跳过
            if depth >= self.depth_limit:
                continue
                
            # 如果到达目标节点
            if current == goal:
                # 重构路径
                path = self._reconstruct_path(parent, current)
                return path
                
            # 检查所有邻居节点
            for dr, dc in directions:
                neighbor = (current[0] + dr, current[1] + dc)
                
                # 检查邻居节点是否在网格范围内
                if not (0 <= neighbor[0] < rows and 0 <= neighbor[1] < cols):
                    continue
                    
                # 检查邻居节点是否为障碍物
                if grid[neighbor[0]][neighbor[1]] == 1:
                    continue
                    
                # 检查邻居节点是否已访问
                if neighbor in visited:
                    continue
                    
                # 标记为已访问并加入栈
                visited.add(neighbor)
                parent[neighbor] = current
                stack.append((neighbor, depth + 1))
                
        # 未找到路径
        return None
        
    def _reconstruct_path(self, parent: Dict[Tuple[int, int], Tuple[int, int]], current: Tuple[int, int]) -> List[Tuple[int, int]]:
        """
        重构路径
        
        Args:
            parent: 父节点字典
            current: 当前节点
            
        Returns:
            路径坐标列表
        """
        path = [current]
        while current in parent:
            current = parent[current]
            path.append(current)
        path.reverse()
        return path
        
    def get_stats(self) -> Dict[str, int]:
        """
        获取算法统计信息
        
        Returns:
            统计信息字典
        """
        return self.stats.copy()
        
    def set_depth_limit(self, limit: int):
        """
        设置深度限制
        
        Args:
            limit: 深度限制
        """
        self.depth_limit = limit