zoukankan      html  css  js  c++  java
  • 过河问题代码学习与总结

    1. 过河问题代码
    2. allSubsets()函数说明
    3. util文件代码
    4. heapq的简单学习和示例代码

    过河问题源代码:

    import util
    # 返回一个集合的所有小于limit的子集:s=(1,4), return [(1,4),(1),(4),()]
    def allSubsets(s, limit):
        if len(s) == 0 or limit == 0:#递归结束的条件,在len(s) == 0 or limit == 0
            return [[]]
        return [[s[0]] + r for r in allSubsets(s[1:], limit-1)] + allSubsets(s[1:], limit) #使用递归的方法求解
    
    class CrossRiverProblem:
        # what is a state e.g. ((1,1,1,1,1), 0),((0,1,1,0,1), 0),前面表示动物,后面表示人。
        # state 状态
        #N表示一共有多少个动物,S表示一个船一次载多少动物
        def __init__(self, N, S):
            self.N = N #N=5
            self.S = S #S=2
    
        # Return start state ((0,0,0,.....,0),0)
        def startState(self):
            return (tuple(0 for _ in range(self.N)), 0)#返回一个tuple,
    
        # Return TRUE if state is a goal state ((1,1,.....,1),1)
        def isEnd(self, state):
            return state == ((tuple(1 for _ in range(self.N))), 1)
        # Return a list of successor states and costs
        # (后继节点和代价 of state)
        def succAndCost(self, state):
            print("expand: " + str(state))
            animals = state[0]
            ship = state[1]
            result = []
            #判断在船上的小动物,当小动物在船上的时候,小动物的状态和人的状态是一样的,所以可以用animals[i] == ship 表示。
            # i 表示的是小动物的索引,这样就知道了这个动物是哪一个动物。
            # s 是在船上的动物的所有组合的表示。
            for s in allSubsets([i for i in range(self.N) if animals[i] == ship], self.S):
                temp = list(animals)#tuple转变为list的可以修改形式。
                for i in s:
                    temp[i] = 1-ship  #在船的状态再次发生变化的时候,将携带的动物的状态也发生改变。
    
                newState = (tuple(temp), 1-ship)
                if self.isValidState(newState):#判断新的状态是不是满足条件。
                    result.append((newState, 1))#这个1 是cost,
            return result #返回所有后继节点和cost
    
        def isValidState(self, state):
            animals = state[0]
            ship = state[1]
            for i in range(self.N - 1):
                if animals[i] != ship and animals[i+1] != ship:  #认为连续的两个动物和船的状态不一样是不满足条件的。
                    return False
            return True
    
    # 等代价搜索
    # (TotalCost of optimal solution, history of solution)
    def uniformCostSearch(problem):
        state = problem.startState()
        open = util.PriorityQueue()  #创建一个priorityQueue()类的实例。
        open.update(state, 0)
        while True:
            state, pastCost = open.removeMin()
            if problem.isEnd(state):  #出open表的时候,看一下是不是满足条件。
                print("Total cost: " + str(pastCost))
                return pastCost, []
            for newState, cost in problem.succAndCost(state):
                open.update(newState, pastCost + cost)
    
    
    problem = CrossRiverProblem(N=5, S=2)  #创建一个类的实例并且初始化。
    print(uniformCostSearch(problem))
    
    
    
    def AstarSearch(problem, h):
        state = problem.startState()
        open = util.PriorityQueue()
        open.update(state, h(state))
        costs = {state: 0}
        parents = {state: None}
        while True:
            state, pastCost = open.removeMin()
            if problem.isEnd(state):
                print("Total cost: " + str(pastCost - h(state)))
                history = []
                track = state
                while track:
                    history.append(track)
                    track = parents[track]
                return pastCost, history
            for newState, cost in problem.succAndCost(state):
                open.update(newState, pastCost + cost - h(state) + h(newState))
                if newState not in costs or costs[newState] > pastCost + cost:
                    costs[newState] = pastCost + cost
                    parents[newState] = state
    
    def printSolution(solution):
        history = solution[1]
        for s in history:
            print(s)
    
    printSolution(AstarSearch(problem, lambda x: 0))
    

    allSubsets()函数说明:

    allSubsets()函数使用了递归的写法,基本的思路是,求解一个集合的子集的时候,首先我们把这个集合划分为两个部分,一部分是这个集合的第一个元素,一部分是这个集合除了
    第一个元素的后面的元素,然后我们让第一个元素和后面的元素组合求解集合的子集,再在后面的集合里面使用同样的方法求解这个集合的子集,之后将两部分的结果汇总成一部分,
    放在一个list里面。这个函数还加了一些限制,我们使用limits变量控制奇求解的集合的长度,这个判断标准就是放在了递归出口的地方。也作为程序的出口。
    

    util文件代码源代码:

    import heapq, collections, re, sys, time, os, random
    # Data structure for supporting uniform cost search.
    class PriorityQueue:
        def  __init__(self):
            self.DONE = -100000
            self.heap = []
            self.priorities = {}  # Map from state to priority
        # Insert |state| into the heap with priority |newPriority| if
        # |state| isn't in the heap or |newPriority| is smaller than the existing
        # priority.
        # Return whether the priority queue was updated.
        def update(self, state, newPriority):
            oldPriority = self.priorities.get(state)
            if oldPriority == None or newPriority < oldPriority:
                self.priorities[state] = newPriority
                heapq.heappush(self.heap, (newPriority, state))
                return True
            return False
    
        # Returns (state with minimum priority, priority)
        # or (None, None) if the priority queue is empty.
        def removeMin(self):
            while len(self.heap) > 0:
                priority, state = heapq.heappop(self.heap)
                if self.priorities[state] == self.DONE: continue  # Outdated priority, skip
                self.priorities[state] = self.DONE
                return (state, priority)
            return (None, None) # Nothing left...
    

    heapq的学习

    import heapq
    def heapsort(iterable):
        h  = []
        for value in iterable:
            heapq.heappush(h,value)
        print(heapq.heappop(h))  # -2
        print(heapq.heappushpop(h,-1))  #- 1
        print(heapq.heapreplace(h,10))  # 1
    iterable = [1,3,5,7,9,2,4,6,8,-2]
    heapsort(iterable)
    h = [1,3,5,7,9,2,4,6,8,-2]
    heapq.heapify(h)
    h #变成堆的结果[2, 1, 2, 6, 3, 5, 4, 7, 8, 9]
    

    heapq是python中的堆队列算法模块,也称为优先级队列算法模块,详细的学习文档请点击python标准库学习。
    heapq的基本功能:
    heapq.heappush(堆,项目) 将值推入堆中,保持堆不变。
    heapq.heappop(堆) 弹出并从堆中返回最小的顶,从而保持堆不变,要访问最小的项目但是不弹出,可以使用heap[0]
    heapq.heappushpop(堆,项目)将项目推入堆中,然后弹出并从堆中返回最小的项目
    heapq.heapify(x) 将列表X在线性时间内就地转换为堆

  • 相关阅读:
    Object类-try-catch-finally-throw-throws-自定义异常
    修饰符-包-内部类-代码块执行顺序
    ZOJ 1241 Geometry Made Simple
    ZOJ 1029 Moving Tables
    ZOJ 1047 Image Perimeters
    ZOJ 1024 Calendar Game
    动态规划 -- 01背包问题
    Kmeans算法的应用实例(Matlab版本)
    Matlab优化存储器读写来改善程序性能
    struct和typedef struct的区别
  • 原文地址:https://www.cnblogs.com/cccf/p/12674204.html
Copyright © 2011-2022 走看看