深度优先搜索--python

#coding:utf-8
import scrapy
import xlwt, lxml
import re, json
import matplotlib.pyplot as plt
import numpy as np
import pylab
from scipy import linalg
import math

'''
深度优先搜索DFS
    理念:不断深入,‘走到头’回退(回溯思想)
        一般所谓‘暴力枚举’搜索都是指DFS
    实现:一般使用堆栈,或者递归
    用途:DFS过程中,能够获得的信息:
        时间戳,颜色,父子关系,高度

    优点:由于只保存了一条路径,空间重复利用
#无论BFS,DFS找到解和解的‘位置’有关
'''

'''回文划分问题
给定一个字符串s,将s划分成若干子串,使得每一个字串都是回文串。计算所有s的可能的划分
eg:s='aab',-->'aa','b';'a','a','b'
在每一步都可以判断中间结果是否为合法结果:回溯法--如果某一次划分不合法,立刻对该分支限界
一个长度为n的字符串,有n-1个位置可以截断,每个位置可断可不断,故时间复杂度为O(2^(n-1))
'''
def isPalindrome(str,start,end):#判断分段子串是否回文,并返回布尔类型(起始位置是否大于结束位置)【不是回文串,则返回False】
    while start<end and str[start]==str[end]:
        start+=1
        end-=1
    return start>=end
def DFS(str,start,result,path):
    if start==len(str):
        if not path in result:
            result.append(path)
        print(result)
        return
    for i in range(start,len(str)):
        if isPalindrome(str,start,i):

            path.append(str[start:i+1])#是回文串,则将路径添加到结果列表中
            DFS(str,i+1,result,path)#从下一段开始继续划分
            path.pop()#向上一级回溯

# DFS('aab',0,[],[])




#类似的,给定仅包含数字的字符串,返回所有可能的有效IP地址组合
#   eg:'25525511135',返回'255.255.11.135';'255.255.111.35'
    #该问题插入三个分割位置;只有添加了第三个分割字符后,才能判断当前划分是否合法
    # eg:2.5.5.25511135,才能判断出是非法的

def isValid(str,start,end):
    if start<end:
        return math.floor(int(str[start:end])/256)<1
    else:
        return False

def DFS2(str,start,result,path):
    if start==len(str) and len(path)==4:
        result.append('.'.join(path))
        print(result)
        return
    for i in range(start,len(str)):
        if isValid(str,start,i+1):
            path.append(str[start:i+1])
            # print(path)
            DFS2(str,i+1,result,path)
            path.pop()

# DFS2('25525511135',0,[],[])

'''
八皇后问题:
    N*N矩阵,放置N个元素,且任意两个元素不能处于同一行、同一列、同一(主/副)对角线上,问有多少种解法?
'''
#全排列
# def isSwap(f,to):
#     bCan=True
#     for i in range(f,to):
#         if (s[to]==s[i]):
#             bCan=False
#             break
#     return bCan
#
# def permutation(f,to,c):
#     if f==to:
#         print(''.join(s))
#
#         return 1
#     for i in range(f,to+1):
#         if(isSwap(f,i)==False):
#             continue
#         t=s[f]#将首字符和后续字符交换
#         s[f]=s[i]
#         s[i] = t
#         permutation(f+1,to,c)#依次递归
#         #交换回来保持原顺序不变
#         t = s[i]
#         s[i] = s[f]
#         s[f] = t
#         # print(''.join(s))
#
# s=list('01234567')
# l=len(s)
# # print(l)
# permutation(0,l-1,[])

'''
分析:显然任意一行有且仅有1个皇后,使用数组queen[0...7]表示第i行的皇后放到哪一列
    对于‘12345678’字符串,调用全排列问题的代码,并且加入分支限界的条件判断是否相互攻击即可
    
    此外,也可以使用深度优先的想法,将第i个皇后放置在第j列上,如果当前位置与其他皇后相互攻击,则剪枝掉该结点[可拓展到n皇后问题]
'''
def queen(arr,cur=0):#cur为当前行数
    if cur==len(arr):
        print(arr)
        return
    for col in range(0,len(arr)):
        arr[cur],flag=col,True
        for row in range(0,cur):
            if arr[row]==col or abs(arr[cur]-arr[row])==cur-row:#剪枝条件,同列或同对角线
                flag=False
                break
        if flag:#下一行
            queen(arr,cur+1)

# queen([None]*8)


#数独Sudoku【9*9】,初始化用‘.’表示,每行、每列、每个九宫格内,都是1-9这9个数字

def sudoku(arr):
    for i in range(len(arr)):
        for j in range(len(arr)):
            if arr[i][j]=='.':
                for k in range(len(arr)):
                    arr[i][j]=1+k
                    # print(arr)
                    if isValid2(arr,i,j) and sudoku(arr):
                        # print(arr)
                        return True
                    arr[i][j]='.'
                return False

    return True

def isValid2(arr,x,y):
    print(arr)
    for i in range(len(arr)):#判断除x行外的所有行某列
        # print(arr[i][y])
        if i!=x:
            # print(arr[i][y])
            if arr[i][y]==arr[x][y]:
                # print(arr[x][y])
                # print('1')
                return False
    for j in range(len(arr)):#判断列
        if j!=y and arr[x][j]==arr[x][y]:
            print('2')
            return False
    for i in range(3*(math.floor(x/3)),3*(math.floor(x/3)+1)):
        for j in range(3*(math.floor(y/3)),3*(math.floor(y/3)+1)):
            if (i !=x or j!=y)and arr[i][j]==arr[x][y]:#判断小九宫格
                print('3')
                return False
    return True


'''
Tarjan算法:深度优先
    由Robert Tarjan在1979年发现的一种高效离线算法。即,它要首先读入所有的询问(求一次LCA叫做一次访问),然后并不一定按原来的顺序处理这些访问。
    算法时间复杂度O(N*α(N)+Q),其中α(x)不大于4,N表示问题规模,Q表示询问次数

'''

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值