IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> POJ-2286 The Rotation Game + Python(DFS) -> 正文阅读

[数据结构与算法]POJ-2286 The Rotation Game + Python(DFS)

题目链接:poj 2286 The Rotation Game-面试哥

题目目的:通过沿8个方向旋转,使得中间8个元素的数值相同,示例如下:

?一?解题说明

#1 注意事项:Rotation时,需要重新赋值矩阵数据,否则将前后一起变化。
#2 注意事项:用队列存储操作过程,在将队列赋值给新队列时,需要特别注意队列中的元素顺序,因为它对应着操作顺序。

? ? ? ? ? ? ? ?  new_step = []
? ? ? ? ? ? ? ?  new_step.append(dir_i)
? ? ? ? ? ? ? ?  for step_i in step:
? ? ? ? ? ? ? ?  ? ? new_step.append(step_i)
? ? ? ? ? ? ? ?  # 要保证顺序不能变,否则最终输出时,顺序将有误
? ? ? ? ? ? ? ?  new_step.append(dir_i) # 在尾部添加
? ? ? ? ? ? ? ?  # 并将头部的数据去除
? ? ? ? ? ? ? ?  new_step.pop(0)

# 提前设置各操作对应的数字:
# 设置操作标志
action = {0:['A'],1:['B'],2:['C'],3:['D'],4:['E'],5:['F'],6:['G'],7:['H']}

#3 目标元素的确定:统计1/2/3三个元素在目标区域中的个数,以个数最大者对应的元素为目标元素,见findTarget函数
#4 一些法则:
#4.1 旋转一次之后,如果目标元素发生了变化(例如由2变成了3),则return
#4.2 旋转一次之后,如果目标元素未发生变化,但数量减少,则return
#4.3 旋转一次之后,如果目标元素未发生变化,并且数量未减少,则进入下一次dfs搜索;
#5 终止条件
#5.1 目标区域中的目标元素的个数为8,成功return!
#5.1.1 保存当前方案
#5.1.2 存储当前的目标元素
#5.2 如果DFS搜索深度大于设定值,则错误return。
#5.3 假设当前目标元素能够找到可行的方案,则不再对其他目标元素进行搜索。
#5.4 对当前目标元素的所有方案进行分析,选择长度最短、按字母顺序排序的方案。
#5.4.1 将各操作用阿拉伯数字表示,将可行方案拼接成一个字符串,根据字符串对应的数字大小,来确定字母排序最小的方案。

二?代码实现:

# http://www.mianshigee.com/question/16649hrq
import collections
import math

#1 注意事项:Rotation时,需要重新赋值矩阵数据,否则将前后一起变化。
#2 注意事项:用队列存储操作过程,在讲队列赋值给新队列时,需要特别注意队列中的元素顺序,因为它对应着操作顺序。
                # new_step = []
                # new_step.append(dir_i)
                # for step_i in step:
                #     new_step.append(step_i)
                # # 要保证顺序不能变,否则最终输出时,顺序将有误
                # new_step.append(dir_i) # 在尾部添加
                # # 并将头部的数据去除
                # new_step.pop(0)
#3 目标元素的确定:统计1/2/3三个元素在目标区域中的个数,以个数最大者对应的元素为目标元素,见findTarget函数
#4 一些法则:
#4.1 旋转一次之后,如果目标元素发生了变化,则return
#4.2 旋转一次之后,如果目标元素未发生变化,但数量减少,则return
#4.3 旋转一次之后,如果目标元素未发生变化,并且数量未减少,则进入下一次dfs搜索;
#5 终止条件
#5.1 目标区域中的目标元素的个数为8,成功return!
#5.1.1 保存当前方案
#5.1.2 存储当前的目标元素
#5.2 如果DFS搜索深度大于设定值,则错误return。// self.MaxDeep = 4 # 这次数据特别有效,有助于提升算法的执行速度。
#5.3 假设当前目标元素能够找到可行的方案,则不再对其他目标元素进行搜索。
#5.4 对当前目标元素的所有方案进行分析,选择长度最短、按字母顺序排序的方案。
#5.4.1 将各操作用阿拉伯数字表示,将可行方案拼接成一个字符串,根据字符串对应的数字大小,来确定字母排序最小的方案。


# 将数据转存为矩阵
def data2Matrix(subData):
    newData = [[0]*7 for i in range(7)]
    # 将subData的数据填充进入
    for i in range(24):
        if i == 0:
            newData[0][2] = subData[i]
        elif i == 1:
            newData[0][4] = subData[i]
        elif i == 2:
            newData[1][2] = subData[i]
        elif i == 3:
            newData[1][4] = subData[i]
        elif 4<=i<=10:
            newData[2][i-4] = subData[i]
        elif i ==11:
            newData[3][2] = subData[i]
        elif i == 12:
            newData[3][4] = subData[i]
        elif 13<=i<=19:
            newData[4][i-13] = subData[i]
        elif i == 20:
            newData[5][2] = subData[i]
        elif i == 21:
            newData[5][4] = subData[i]
        elif i == 22:
            newData[6][2] = subData[i]
        elif i == 23:
            newData[6][4] = subData[i]
    return newData
# 查找目标区域的元素,并排序
def findTarget(subData):
    # 统计各元素的数量
    num1 = 0
    num2 = 0
    num3 = 0
    # 给定目标区域的坐标列表
    Target_areas = [[2,2],[2,3],[2,4],[3,2],[3,4],[4,2],[4,3],[4,4]]
    # res = ''#存放数据
    for i in range(8):
        rr,cc = Target_areas[i][0],Target_areas[i][1]
        # res = res + str(newData[rr][cc])
        if subData[rr][cc] == 1:
            num1 = num1 + 1
        elif subData[rr][cc] == 2:
            num2 = num2 + 1
        elif subData[rr][cc] == 3:
            num3 = num3 + 1
    ans = [num1,num2,num3]
    min_ans = min(ans)
    max_ans = max(ans)
    targetdict = {}
    for i in range(1,4,1):
        if ans[i-1] == max_ans and 'max' not in targetdict.keys():
            targetdict['max'] = [i,max_ans] # 存档数据说明【元素值,元素数量】
        elif ans[i-1] == min_ans and 'min' not in targetdict.keys():
            targetdict['min'] = [i, min_ans]
        else:
            targetdict['mid'] = [i, ans[i-1]]
    return targetdict
# 设置旋转,并返回旋转后的矩阵和目标区域的字典
def Rotation(Data,dir):
    # 数据需要转存
    subData = []

    for i in range(len(Data)):
        temp = []
        for j in range(len(Data[0])):
            temp.append(Data[i][j])
        subData.append(temp)

    if dir == 0: #沿0方向旋转1次
        temp = subData[0][2]
        for i in range(7):
            if i == 6:
                subData[i][2] = temp
            else:
                subData[i][2] = subData[i+1][2]
    elif dir == 1: #沿1方向旋转1次
        temp = subData[0][4]
        for i in range(7):
            if i == 6:
                subData[i][4] = temp
            else:
                subData[i][4] = subData[i+1][4]
    elif dir == 2:
        temp = subData[2][6]
        for i in range(6,-1,-1):
            if i == 0:
                subData[2][0] = temp
            else:
                subData[2][i] = subData[2][i-1]
    elif dir == 3:
        temp = subData[4][6]
        for i in range(6,-1,-1):
            if i == 0:
                subData[4][0] = temp
            else:
                subData[4][i] = subData[4][i-1]
    elif dir == 4:
        temp = subData[6][4]
        for i in range(6,-1,-1):
            if i == 0:
                subData[0][4] = temp
            else:
                subData[i][4] = subData[i - 1][4]
    elif dir == 5:
        temp = subData[6][2]
        for i in range(6,-1,-1):
            if i == 0:
                subData[0][2] = temp
            else:
                subData[i][2] = subData[i - 1][2]
    elif dir == 6:
        temp = subData[4][0]
        for i in range(7):
            if i == 6:
                subData[4][6] = temp
            else:
                subData[4][i] = subData[4][i+1]
    elif dir == 7:
        temp = subData[2][0]
        for i in range(7):
            if i == 6:
                subData[2][6] = temp
            else:
                subData[2][i] = subData[2][i+1]
    ## 获得旋转后的数据,以及中间的8个目标元素
    targetdict = findTarget(subData)
    return subData,targetdict

# 寻找长度最小的方案,保存起来
def findWays(ways):
    LEN = len(ways)
    if LEN == 1:
        return ways[0]
    else:
        Init_len = math.inf
        FianlWays = []
        for i in range(LEN):
            temp = ways[i][0]
            if len(temp) < Init_len: # 确定方案的最小长度
                Init_len = len(temp)
        for i in range(LEN):# 寻找长度最小的方案
            temp = ways[i][0]
            if len(temp) == Init_len:
                FianlWays.append(ways[i])
    ## 寻找长度相同,但字母排序最小的方案
    LEN = len(FianlWays)
    if LEN==1:
        return FianlWays[0]
    else:
        len2 = len(FianlWays[0][0])
        Init_int = math.inf
        for i in range(LEN):
            temp = FianlWays[i][0]
            res = ''
            for j in range(len2):
                res = res + str(temp[j])
            if int(res) < Init_int: # 查找字母排序最小值
                Init_int = int(res)
        ## 确定字母排序最小值对应的方案
        for i in range(LEN):
            temp = FianlWays[i][0]
            res = ''
            for j in range(len2):
                res = res + str(temp[j])
            if int(res) == Init_int: # 查找字母排序最小值
                return FianlWays[i]

## 开始DFS处理
class Solutions:
    def DFS(self):
        # 设置DFS的最深深度
        self.MaxDeep = 4 # 这次数据特别有效,有助于提升算法的执行速度。
        # 查询目标区域的元素
        targetdict = findTarget(subData)
        # 存放最终结果
        self.FinalWays = []
        for candicate_i in range(3):
            ## 1 初步选定最初的目标元素(数量最多)
            if candicate_i == 0:
                label = targetdict['max'][0]
                label_num = targetdict['max'][1]
            elif candicate_i == 1:
                label = targetdict['mid'][0]
                label_num = targetdict['mid'][1]
            elif candicate_i == 2:
                label = targetdict['min'][0]
                label_num = targetdict['min'][1]
            ## 2 接下来,DFS搜索当前目标元素的所有可行方案
            self.ways = []
            for dir_i in range(8):
                step = [dir_i]
                self.dfs(subData,label,label_num,dir_i,step)
            ## 3 寻找长度最小的方案,保存起来
            if len(self.ways)>0:# 说明已经找到了合适的方案
                # 寻找长度最小的方案,保存起来
                Ways = findWays(self.ways)
                self.FinalWays.append(Ways)
                break
        # 对保存的方案进行处理
        if len(self.FinalWays)>0: # 说明具有可行方案
            # 按照输出要求进行输出。
            return findWays(self.FinalWays)
        else:
            # 说明没有可行方案
            return "No Solution"

    def dfs(self,data,label,label_num,dir,step):
        # 设置旋转,并返回旋转后的矩阵和目标区域的字典
        new_subData, new_targetdict = Rotation(data, dir)
        new_label = new_targetdict['max'][0]
        new_label_num = new_targetdict['max'][1]
        # 什么是否终止:终止1:
        if new_label == label:
            if new_label_num == 8:# 标签未发生变化,并且目标区域都是同一个元素
                self.ways.append([step,label])# 保存当前方案及label
                return
        else:
            return
        # 终止2:如果step超过了预期的深度,则报错返回
        if len(step) > self.MaxDeep:
            return
        ## 2 不满足终止条件,则继续执行
        if new_label == label and new_label_num>=label_num: # 只有当目标元素保持不变,并且数量不减小时,说明有效
            # 进行下一次dfs循环
            for dir_i in range(8):
                new_step = []
                new_step.append(dir_i)
                for step_i in step:
                    new_step.append(step_i)
                # 要保证顺序不能变,否则最终输出时,顺序将有误
                new_step.append(dir_i) # 在尾部添加
                # 并将头部的数据去除
                new_step.pop(0)
                self.dfs(new_subData,new_label,new_label_num,dir_i,new_step)
        else:
            return
        return

## 首先迎接数据,将数据存放到7*7的矩阵中
data = []
while True:
    n = input().strip()
    if len(n) == 1 and int(n)==0:
        break
    # 存入矩阵中
    temp = list(map(int,n.strip().split(' ')))
    data.append(temp)
# print(data)
# case的数量
N = len(data)
# 设置操作标志
action = {0:['A'],1:['B'],2:['C'],3:['D'],4:['E'],5:['F'],6:['G'],7:['H']}

for casei in range(N):
    subData = data[casei]
    # 将数据转化为矩阵
    subData = data2Matrix(subData)
    test = Solutions()
    ans = test.DFS()
    # 打印
    res = ''
    for i in ans[0]:
        res = res + action[i][0]
    print(res)
    print(ans[1])


输入:

1 1 1 1 3 2 3 2 3 1 3 2 2 3 1 2 2 2 3 1 2 1 3 3
1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3
0

输出:

AC
2
DDHH
2

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-24 18:44:08  更:2021-12-24 18:46:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 17:20:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码