[OJ]水位线问题,1.采用回溯法(深度优先遍历求解)2.采用广度优先遍历求解

在这里插入图片描述
1.深度优先遍历

'''
使用回溯法,深度优先遍历

利用栈先进后出的特点,在加水控制水量失败时,
回到最近一次可对水进行加水与否的位置

1.对于给定水量k,是否在[l,r]之间,
是:是否加水(加水y,用掉x,是否在[l,r]之间)
    (不加水y,用掉x,是否在[l,r]之间)
    先尝试加水,如果不满足条件,则回溯到之前位置
否:报错
'''
class SStack(object):
  
    def __init__(self):		  # 初始化栈为空列表
        self.items = []
    
    def is_empty(self):		# 判断栈是否为空,返回布尔值
        return self.items == []

    def peek(self):		  # 返回栈顶元素
        return self.items[len(self.items) - 1]

  
    def size(self):		  # 返回栈的大小
        return len(self.items)

    
    def push(self, item):		# 把新的元素堆进栈里面(入栈)
        self.items.append(item)

 
    def pop(self):		   # 把栈顶元素丢出去(出栈)
        return self.items.pop()
 
def main():
    # code here
    k,l,r,t,x,y=map(int,input().split(" "))
    ControlWaterAmount(k,l,r,t,x,y)



def ControlWaterAmount(k,l,r,t,x,y):
    dirs=[0,y]
    assert l<=k<=r
    #创建栈
    st=SStack()
    #标记当前日期的水量  k

    #入口和方向0、时间t的序对入栈
    st.push((k,0,t))
    while not st.is_empty():#走不通时回退
        #取栈顶及检查方向
        pos,nxt,t=st.pop()
        #依次检查未检查的方向,算出下一方向
        for i in range(nxt,2):
            if l<=pos<=r:
                #当前时刻的偏移量为y(是否加水) 
                nextpos=pos+dirs[i]
            if nextpos>r:
                break

            #到达程序出口
            if l<=pos<=r and t==0:
                print('Yes')
            #遇到未探索的新方向
            if   l<=pos<=r :
                #标记当前时间 t
                    
                #原位置、下一方向、时间t 入栈
                st.push((pos,i+1,t))
                #标记当前日期的水量 nextpos
                nextpos=nextpos-x            
                #新位置入栈
                st.push((nextpos,0,t-1))
                #退出内层循环,下次迭代将以新栈顶作为当前位置继续
                break
            

    print('No')

                 
if __name__ == '__main__':
    main();

提交测评结果:
在这里插入图片描述在这里插入图片描述
原因分析:
当输入的时间t足够大时,会维持一个占内存极大的栈,栈中保存 t到1天的数据,造成超内存。

2.采用广度优先遍历

'''
以队列存储可以探索的位置。利用队列先进先出的特点,
实现在每个分支上同时进行搜索路径,直到找到出口。
广度优先遍历
'''
class SQueue(object):
    """实现一个队列"""

    def __init__(self):
        self.__list = []

    def enqueue(self, elem):
        """入队"""
        self.__list.append(elem)

    def dequeue(self):
        """出队"""
        return self.__list.pop(0)

    def is_empty(self):
        return not self.__list

    def size(self):
        """队列的大小"""
        return len(self.__list)

def ControlWaterAmount_queue(k,l,r,t,x,y):
    dirs=[0,y]
    path=[] #存水量的变化
    #path.append(k)
    qu=SQueue()
    #标记当前日期的水量  k

    #开始水量、开始时间入队
    qu.enqueue((k,t))
    while not qu.is_empty():#当队列中还有候选水量时
        pos,t=qu.dequeue()#取出下一水量和时间
        for i in range(2):#检查每种水量的情况
            if l<=pos<=r:
                nextpos=pos+dirs[i]
            if nextpos>r:
                continue
            if l<=pos<=r and t==0: #到达程序入口
                #path.append(pos)
                print('Yes')
            if l<=pos<=r:#找到新的探索方向
                 #标记当前日期的水量 nextpos
                nextpos=nextpos-x
                qu.enqueue((nextpos,t-1))#新水量入队
    print('No')
            


 
def main():
    # code here
    k,l,r,t,x,y=map(int,input().split(" "))
    #ControlWaterAmount(k,l,r,t,x,y)
    ControlWaterAmount_queue(k,l,r,t,x,y)

                 
if __name__ == '__main__':
    main();

在这里插入图片描述

在这里插入图片描述原因分析:当输入的时间t足够大时,会出现2^t次情况,每种情况都需要进行判断,会消耗大量的时间,直接导致超时

参考内容

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值