回溯法:《圆排列问题》-python实现

给定n个大小不等的圆c1,c2,…,cn,现要将这n个圆排进一个矩形框中,且要求各圆与矩形框的底边相切。圆排列问题要求从n个圆的所有排列中找出有最小长度的圆排列。例如,当n=3,且所给的3个圆的半径分别为1,1,2时,这3个圆的最小长度的圆排列如图所示。其最小长度为


 

#coding:utf-8
import sys
import math
import copy
cc = []


def bianchang(a, l, c):
    if l == 0:
        return 2 * a
    else:
        b = (a + c) ** 2 - (abs(a - c)) ** 2
        return l - c + math.sqrt(b) + a


def compute(d, a, n, l, c):                      #d表示输入半径的列表,a表示第几个半径,n表示半径的总共个数,l表示上一次计算的边长,c表示上一次圆的半径
    d1 = copy.deepcopy(d)                        #对d进行深拷贝
    if a == n:                                   #当计算到第n个半径时,将结果保存在列表cc中
        global cc
        cc.append(l)
        #print cc
    else:
        for i in range(0, len(d1)):
            if d1[i] != 0:
                t = bianchang(d1[i], l, c)      #当加入新的圆时,计算加入后的边长
                w = d1[i]
                d1[i] = 0                       #该半径计算完成后,将其置为0,标志已经计算结束
                compute(d1, a + 1, n, t, w)
                d1[i] = w                       #再将该半径的值恢复,方便下一次的回溯计算


if __name__ == '__main__':
    n = input()                                          #n表示输入半径的个数
    d = sys.stdin.readline().strip().split(' ')          #d表示输入的半径,以空格进行分割
    d = map(int, d)

    compute(d, 0, n, 0, 0)                               #回溯算法

    print min(cc)

 

你可能感兴趣的:(思路较好)