力扣 174. 地下城游戏 DFS + Python

原题链接: 力扣

 备注:最初做本题目是用的动态规划;在做了一些DFS题目之后,发现本题也可以用DFS来做。

一 特别注意

1. 需要特别注意:假设初始时刻的健康点数为Init,那么在进行下一步搜索之前,他的健康点数部分和为:Sum=Init+“起始点的元素值”,即Sum = Init-2。

2. 策略:将题目转化为——设置初始健康点数Init,使得走到目标节点时的健康点数不小于1;

2.1 因此,可将Init从1开始增加,直到满足题目要求停止;

2.2 同时注意,在搜索过程中,部分和Sum不小于1。

二 代码实现

# 174. 地下城游戏
# https://leetcode-cn.com/problems/dungeon-game/

import collections
# import math
def sub2Cors(data):
    data_dict = collections.defaultdict(list)
    hh = len(data)
    ww = len(data[0])
    for i in range(hh):
        for j in range(ww):
            str1 = str(i) + ";" + str(j)
            data_dict[str1] = [data[i][j]]
    return data_dict


class Solution:
    def DFS(self):
        # self.MAX = math.inf
        self.keys = data_dict.keys()
        self.flag = set() #如果存在1,则说明有可行方案;否则,无可行方案
        self.dfs(start,Init + data[0][0]) # 初始时刻的Sum为:起始点的元素值 + 起始节点的健康点数
        if 1 in self.flag:
            return True
        else:
            return False

    def dfs(self,s,Sum):
        # if s == start and Sum+data_dict[s][0] <1: # 初始时刻的健康点数也要为正数
        #     self.flag.add(0)  # 方案无效
        #     return
        if s == target and Sum >=1:
            self.flag.add(1)  # 方案有效
            return
        # 获得当前节点的坐标
        rr,cc = map(int,s.split(";"))
        nodes = []
        node1 = str(rr) + ";" + str(cc+1)
        node2 = str(rr+1) + ";" + str(cc)
        if node1 in self.keys and Sum + data_dict[node1][0] >=1:# 如果不越界,并且部分和大于等于1
            nodes.append(node1)
        if node2 in self.keys and Sum + data_dict[node2][0] >=1:
            nodes.append(node2)
        if len(nodes) == 0:
            self.flag.add(0) # 方案无效
            return
        # 对各节点进行处理
        for i in nodes:
            # 当前节点为i
            # 其元素值为:
            new_sum = Sum + data_dict[i][0]
            self.dfs(i,new_sum)

        # 说明方案无效
        self.flag.add(0)  # 方案无效
        return





## 重新用DFS来做这个题目
data = [[-2,-3,3],[-5,-10,1],[10,30,-5]]
print(data)
hh = len(data)
ww = len(data[0])
start = "0;0"
target = str(ww-1) + ";" + str(ww-1)
print(start,target)
# 挨个尝试:将初始健康点数设置为1,2,... 递增,直到找到合适的方案
Init = 1
while True:
    # 将数据转化为索引
    data_dict = sub2Cors(data)
    # 开始循环检测吧:
    test = Solution()
    ans = test.DFS()
    ## 成功,则break
    if ans:
        print(Init) #
        break
    else:
        Init = Init+1

版本二:

import collections
import math

## 迎接数据
data = []
str1 = input().strip()
str1 = str1[2:-2].split('],[')
R = len(str1)
for i in range(R):
    temp_str = list(map(int,str1[i].split(',')))
    data.append(temp_str)
C = len(temp_str)
print(R,C)
## 数据预处理
def sub2Dict(data,R,C):
    dict = collections.defaultdict(list)
    index = []
    for i in range(R):
        temp = data[i]
        for j in range(C):
            sub = temp[j]
            str1 = str(i)+';'+str(j)
            index.append(str1)
            dict[str1] = [sub,i,j]
            
    return index,dict
    
index,dict = sub2Dict(data,R,C)
print(index,dict)
####
class Solutions:
    def DFS(self,sumi):
        node = '0;0'
        self.target = '2;2'
        self.Flag = False
        self.dfs(node,sumi)
        return self.Flag       
    def dfs(self,node,sumi):
        ## 判断是否有效
        if dict[node][0] + sumi <1:
            return False        
        ## 判断是否到达终点
        if node == self.target:
            self.Flag = True
            return True
        ## 正常情况        
        rr,cc = map(int,node.split(';'))
        node1 = str(rr+1)+';'+str(cc)
        node2 = str(rr)+';'+str(cc+1)
        nodes = []
        if node1 in index:
            nodes.append(node1)
        if node2 in index:
            nodes.append(node2)
        if len(nodes)==0:
            return False
        ## 
        for i in nodes:
            if self.dfs(i,dict[node][0] + sumi):
                return True
        return False
        
### 
All = R*C
for i in range(1,All):
    test = Solutions()
    ans = test.DFS(i)
    if ans == True:
        break
print(i)
        
    

输入:

[[-2,-3,3],[-5,-10,1],[10,30,-5]]

输出:

7

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值