POJ 3009 - Curling 2.0 + Python DFS

原题链接及参考资料:

# http://poj.org/problem?id=3009
# https://exp-blog.com/algorithm/poj/poj3009-curling-2.0/

一 注意事项

        1 初始时刻的运动状态为“静止”,接下来有4种运动方向:上下左右

        3 当状态为运动时,下一步进行判断:

                3.1 继续运动

                3.2 遇到石头,则停止,并击碎石头

                3.3 遇到终点,停止运动,不击碎,返回

        2 由于寻找具有最小路径的一种方案,因此设置一种参数,用于比较每一方案的路径大小,并且更新其值为最小路径数(在本程序中,该参数是self.MaxStep)。

        3 提前设置下一步的坐标更新列表:

# 首先定义移动的方向
dir = {0:[-1,0],1:[0,-1],2:[1,0],3:[0,1]}
# North:0,West:1,South:2,East:3

二 代码实现

# http://poj.org/problem?id=3009
# https://exp-blog.com/algorithm/poj/poj3009-curling-2.0/

import collections
# 将数据转化为索引,并返回新数据、字典、起始点和终止点
def sub2cor(subData,hh,ww):
    data_dict = collections.defaultdict(list)
    temp = []
    count = 0
    for i in range(hh):
        # 注意每行数据之间有空格,需要处理空格
        res = subData[i].split(' ')
        for j in range(ww):
            if res[j] == '2':
                # 确定为起始点
                start = str(i)+";"+str(j)
                # 修改元素值为0
                res[j] = '0'
            elif res[j] == '3':
                target = str(i)+";"+str(j)
            # 添加到字典中
            temp.append(res[j])
            data_dict[str(i)+";"+str(j)] = [count,res[j]]
            count +=1
    return temp,data_dict,start,target

class Solution:
    def DFS(self,s,target):
        # 获得键值
        self.keys = data_dict.keys();
        # # 最大步数
        self.MaxStep = 11
        # # 总步数
        # self.steps = 0
        # 开始执行吧
        self.dfs(s,False,0,0,False)#起始节点+静止+方向为0+计数为0+不击碎石头(特别注意:初始时刻的状态为静止,而不是运动)
        return self.MaxStep
    def dfs(self,s,Status,face,step,RmStone):# s表示当前节点的坐标,Status:表示当前状态,True为运动,False为静止,face:表示运动的方向,step:用于记录步数,Rmstone:表示是否移除石头,True移除
        # 获取当前节点的坐标
        hh,ww = map(int,s.split(";"))
        # 判断是否等于目标点
        if s == target:
            if step< self.MaxStep: #直到找到具有最短路径的一种方案
                self.MaxStep=step
                return
        # 当需要击碎石头时
        if RmStone:# 当击碎石头时,修改当前方向下的下一步格子的元素值,将其变为‘0’
            # 修改数据中的元素信息
            stone_hh = dir[face][0] + hh;
            stone_ww = dir[face][1] + ww;
            new_str = str(stone_hh) + ";" + str(stone_ww) #获得当前方向下的下一步格子的坐标
            data_dict[new_str][1] = '0'
        # 当前状态为静止时,接下来就要移动了(有4种运动方向),并且不再击碎石头
        if Status == False: #当前状态为静止
            # 有东西南北4个节点可以走
            for i in range(4):
                # 下一个节点的坐标
                stone_hh = dir[i][0] + hh;
                stone_ww = dir[i][1] + ww;
                new_str = str(stone_hh) + ";" + str(stone_ww)
                # 判断是否在已知键值中,并且元素值不为1
                if new_str in self.keys:
                    if data_dict[new_str][1] != '1':
                        # 此时可以运动了
                        self.dfs(new_str,True,i,step+1,False) #新坐标,运动,方向沿i,步数+1,不击碎石头
        elif Status == True: #当前状态为移动
            # 接下来的状态有:1 继续运动 2 遇到石头,则停止,并击碎石头 3 遇到终点,停止运动,不击碎,返回
            stone_hh = dir[face][0] + hh;
            stone_ww = dir[face][1] + ww;
            new_str = str(stone_hh) + ";" + str(stone_ww)
            if new_str in self.keys:
                if data_dict[new_str][1] == '0':  # 下一位置为0且不越界,继续运动
                    self.dfs(new_str, True, face, step, False)  # 继续运动时,step不更新
                elif data_dict[new_str][1] == '1':  # 下一位置为1且不越界,停止运动,并消除下一位置的石头
                    self.dfs(s, False, face, step, True)  # 停止运动时,不更新坐标;击碎石头时,step不更新
                elif data_dict[new_str][1] == '3':  # 下一位置为3且不越界,运动到位置3后停止运动,游戏结束
                    self.dfs(new_str, False, face, step, False)
            else:  # 如果越界,则返回
                return
            # if new_str in self.keys and data_dict[new_str][1] == '0': #下一位置为0且不越界,继续运动
            #     self.dfs(new_str,True,face,step,False) #继续运动时,step不更新
            # elif new_str in self.keys and data_dict[new_str][1] == '1': #下一位置为1且不越界,停止运动,并消除下一位置的石头
            #     self.dfs(s,False,face,step,True) #停止运动时,不更新坐标;击碎石头时,step不更新
            # elif new_str in self.keys and data_dict[new_str][1] == '3': #下一位置为3且不越界,运动到位置3后停止运动,游戏结束
            #     self.dfs(new_str, False, face, step, False)
            # else: # 如果都不满足,则返回到上一步的静止状态,然后去更新4个运动方向
            #     return
        # 如果执行到这里还未结束,说明4个方向的路均不通,需要返回上一次迭代 # 回溯前还原石头,即还原上一步的棋盘状态
        if RmStone:
            stone_hh = dir[face][0] + hh;
            stone_ww = dir[face][1] + ww;
            new_str = str(stone_hh) + ";" + str(stone_ww)
            data_dict[new_str][1] = '1'
        return


## 迎接输入
data = [] #注意,读入的数据为字符型,而不是整形(除非自己转化)
data_size = []
#
while True:
    W,H = map(int,input().strip().split(' '))
    if W==0 and H==0:
        break
    else:
        data_size.append([W,H])
    temp = []
    for i in range(H):
        temp.append(input().strip())
    data.append(temp)
# print(data)
# print(data_size)
#
## 也应该考虑索引转坐标吧
# 首先定义移动的方向
dir = {0:[-1,0],1:[0,-1],2:[1,0],3:[0,1]}
# North:0,West:1,South:2,East:3
# 组数n
n = len(data_size)
# 初始化最大步数
MaxStepss = 11
# 分别对每组数据进行处理
for i in range(n):
    # 获取当前数据及数据大小
    subData = data[i]
    ww,hh = data_size[i][0],data_size[i][1]
    # 将数据转化为索引,并返回新数据、字典、起始点和终止点
    subData,data_dict,s,target = sub2cor(subData,hh,ww)
    # print(subData,data_dict,s,target)
    # 开始处理
    test = Solution()
    ans = test.DFS(s,target)
    if ans < MaxStepss:
        print(ans)
    else:
        print("-1")


输入:

2 1
3 2
6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1
6 1
1 1 2 1 1 3
6 1
1 0 2 1 1 3
12 1
2 0 1 1 1 1 1 1 1 1 1 3
13 1
2 0 1 1 1 1 1 1 1 1 1 1 3
0 0

输出:

1
4
-1
4
10
-1

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值