回溯法


算法框架

  1. 非递归
    int a[n],
    i;初始化数组a[];
    i = 1;
    while (i > 0(有路可走) and(未达到目标)) // 还未回溯到头
    {
     if (i > n) // 搜索到叶结点
     {
         搜索到一个解,输出;
     } 
     else // 处理第i个元素
     {
         a[i]第一个可能的值;
         while (a[i]在不满足约束条件且在搜索空间内) {
             a[i]下一个可能的值;
         }
         if (a[i]在搜索空间内) {
    : 标识占用的资源;20 : i = i + 1; // 扩展下一个结点  21:          }  22:          else  23:         {
             清理所占的状态空间; // 回溯25:               i = i –1; 
         }
     }
    }
    
  2. 递归

    回溯法是对解空间的深度优先搜索,在一般情况下使用递归函数来实现回溯法比较简单,其中i为搜索的深度,框架如下

    int a[n];
    try(int i)
    {
     if(i>n)
        输出结果;
      else
     {
        for(j = 下界; j <= 上界; j=j+1)  // 枚举i所有可能的路径
        {
           if(fun(j))                 // 满足限界函数和约束条件
             {
                a[i] = j;
             ...                         // 其他操作
                try(i+1);
              回溯前的清理工作(如a[i]置空值等);
              }
         }
     }
    }
    

三着色问题

一个无向图,邻接矩阵存储,输出所有可能的三着色结果

  1. 递归 ```python def color(level): for i in range(1,4):
     c[level] = i
     if ok(c):
         print(c)
     else:
         color(level+1)
    

a = [[0,1,1,0], [1,0,1,1], [1,1,0,1], [0,1,1,0]] c = [0,0,0,0] k = 1 flag = False color(0)

2. 非递归
```python
def ok(level):
    l = list()
    for i in c:
        if i!=0 and i in l:
            return 0
        elif i!=0 and i not in l:
            l.append(i)
        else:
            return 1
    return 6

a = [[0,1,1,0],
     [1,0,1,1],
     [1,1,0,1],
     [0,1,1,0]]
c = [0,0,0,0,0] # 1,2,3有效
k = 1
flag = False
while k>=1:
    while c[k]<=2:
        c[k] += 1
        if ok(c) == 6:
            print(c)
        elif ok(c) == 1:
            k += 1
    c[k] = 0
    k -= 1

全排列

# -*- coding:utf-8 -*-
'''
全排列问题
回溯法
'''
Count = 0  # 记录迭代的次数
MaxDeep = 3
List = [0] * (MaxDeep+1)

def Try(CurDeep):
    '''探索第CurDeep层'''
    global Count
    for i in range(List[CurDeep]+1, MaxDeep+1):
        Count += 1
        List[CurDeep] = i
        if OK(CurDeep): #前面符合条件=>继续深一层Try
            if CurDeep == MaxDeep:
                print(List[1:])
                break
            Try(CurDeep+1)
    List[CurDeep] = 0

def OK(CurDeep):
    s = set(List[1:CurDeep+1])
    if len(s) == CurDeep:
        return True
    else:
        return False

if __name__ == "__main__":
    Try(1)
    print("Count:",Count)

素数环问题

链接 解法

  1. 注意正序反序都一样,平移以后也一样
  2. 锁定第一个恒为1即可锁定 TODO :需要优化
# -*- coding:utf-8 -*-
'''
素数环问题
回溯
'''
Count = 0  # 记录迭代的次数
MaxDeep = 8
List = [0] * (MaxDeep + 1)
AllPrimeNumber = [x for x in range(3, 2 * MaxDeep, 2)]  # 存储所有的素数

def Try(CurDeep):
    '''探索第CurDeep层'''
    global Count
    start = 2 - CurDeep%2 # 前后一定一奇一偶,第一个已锁定为1,后续奇偶确定
    for i in range(start, MaxDeep + 1, 2): # 恒为奇数或偶数
        Count += 1
        List[CurDeep] = i
        if OK(CurDeep) == 1:  #前面符合条件=>继续深一层Try
            if CurDeep == MaxDeep:
                print(List[1:-1])
                break
            Try(CurDeep + 1)

def OK(CurDeep):
    if List[CurDeep] in List[1:CurDeep]:  # 当前的值不能和之前的重复
        return False  # 这个判断力度最大,有效减少不必要的判断

    for i in range(1, CurDeep):
        if List[i] + List[i + 1] not in AllPrimeNumber:
            return False

    if CurDeep == MaxDeep:  # 如果是最后一层,还要判断和第一个元素是否满足
        if List[CurDeep] + List[1] not in AllPrimeNumber:
            return False
    return True


if __name__ == "__main__":
    for i in range(1, MaxDeep * 2, 2): # 将不是素数的奇数删除
        for ii in range(2, int(1 + i / 2)):
            if i % ii == 0:
                AllPrimeNumber.remove(i)
                break
    List[1] = 1
    Try(2) # 第一个锁定,从第二个开始
    print("Count:", Count)

组合问题

# -*- coding:utf-8 -*-
'''
组合问题 , 相比全排列,三处改动
回溯法
'''
Count = 0  # 记录迭代的次数
MaxDeep = 3
MaxValue = 4
List = [0] * (MaxDeep+1)

def Try(CurDeep):
    '''探索第CurDeep层'''
    global Count

    # 相比全排列,两处改动
    # for i in range(List[CurDeep]+1, MaxDeep+1): #全排列
    for i in range(List[CurDeep-1]+1, MaxValue+1): 
        Count += 1
        List[CurDeep] = i
        if OK(CurDeep): #前面符合条件=>继续深一层Try
            if CurDeep == MaxDeep:
                print(List[1:])
                # break # 全排列
                continue
            Try(CurDeep+1) # 没到最后一层
    List[CurDeep] = 0

def OK(CurDeep):
    s = set(List[1:CurDeep+1])
    if len(s) == CurDeep:
        return True
    else:
        return False

if __name__ == "__main__":
    Try(1)
    print("Count:",Count)

二维平面上的回溯法

leetcode79. 单词搜索

leetcode 200. 岛屿的个数

floodfill算法,一类经典问题

N皇后

results matching ""

    No results matching ""