求一堆字数中,某几个数字之和等于特定值的情况

求一堆字数中 某几个数字之和等于特定值的情况

问题的产生:

  这个奇思妙想首先来自于我的一个会计的同学(哦,该死的)可能是有业务上的需求吧,了解之后,我在网上搜了很多,绝大多数都说用Excel的规划求解(规划个毛线,连Excel都没沾过边),里面确实也有一些编程程序,在分析了他们的思路之后,我觉得并不靠谱,于是在python功夫不扎实的情况下(主要还是鼓捣了老半天也没个思路),找到了@Inori(事实证明果然很靠谱)

代码:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Inori

def WriteFile(file1): #写文件
    f = open("plus.txt", "a") #这里写文件要用a,因为每次循环输出到文件不能清空文件
    f.write(str(file1))
    f.write('\n')
    f.close()

def QuickSort(str1): #从小到大,并把负数调到列表最后
    for i in range(0, len(str1)):
        for j in range(0, i):
            if str1[j] > str1[i]:
                t = str1[j]
                str1[j] = str1[i]
                str1[i] = t
    for i in range(len(str1)-1, -1, -1):
        if str1[i] < 0:
            t = str1[i]
            str1.remove(t)
            str1.append(t)
    return str1

def queue(str1): #将列表数据从大到小排序
    for i in range(0, len(str1)):
        for j in range(0, i):
            if str1[j] < str1[i]:
                t = str1[j]
                str1[j] = str1[i]
                str1[i] = t
    return str1

def GNN(number, n_small): #二次遍历嵌套,传进来的是没有n_small的数组和要求的n_small
    for i in range(len(num)-1, -1, -1): #后序遍历
        plus = 0
        number_small = [] #用来求n的和的数组
        for j in range(i, -1, -1): #前面几句和FNN一样
            #   下面的大判断,第一个判断不用说,第二个是为了防止重复number中的值,比如number中有1,而4能分成3,1,此时就不能这样分
            #第三个条件是避免FNN传进来的某个不能分的数而耽误时间,[19,1]传进来的n_small=1,就不用再分了
            if plus + num[j] < n_small and num[j] not in number and num[j] != n_small:
                number_small.append(num[j])
                plus = plus + num[j]

            elif plus + num[j] == n_small and num[j] not in number and num[j] != n_small: #同上
                number_small.append(num[j])
                NumberPlus = queue(number + number_small) #这个就是没有n_small的数组加上n_small求和的数组
                if NumberPlus not in ReNumber:  #避免重复
                    #print("副要:%s" % NumberPlus)
                    ReNumber.append(NumberPlus)

                ###下面的类似FNN###
                if len(number_small) > 1:
                    for k in range(0, len(number_small)):
                        temp = number_small[k]
                        number_small.remove(temp)
                        GNN(queue(number + number_small), temp) #里面的排序可以不用,下次嵌套会排序,这里保险
                        number_small.append(temp)
                        number_small = queue(number_small)
                break

def FNN(n): #首次遍历嵌套
    for i in range(len(num)-1, -1, -1): #后序遍历
        number = []     #这个数组是用来存储一次和为n的,比如[n],[n-1,1]
        plus = 0    #这个就是和了,判断和20的关系
        for j in range(i, -1, -1):  #二层循环,
            if plus + num[j] < n:    #累计求和,判断和n的关系
                number.append(num[j])   #如果小于n,就加入数组num
                plus = plus + num[j]    #这个时候才把和加到plus里面

            elif plus + num[j] == n:    #等于n的情况
                number.append(num[j])
                number = queue(number)    #将得到的数组排序成从大到小,作用后面会讲到

                if number not in ReNumber:  #避免重复
                    ReNumber.append(number)     #将得到的一种情况存储起来
                #print("主要:%s" % number)    #可以不用,但是可以让人很清楚的看结果

                if len(number) > 1:     #防止[20]这个情况也会进入循环
                    for k in range(1, len(number)):     #开始调用另一个函数,这里不能取第一个数,所以从1开始
                        t = number[k]      #把number[k]先转给t,不然下面的remove就把这个数给删了
                        number.remove(t)      #把number[k]先去了
                        GNN(number, t)    #此时传进去的就是没有number[k]的数组,因为我们要求t的和的情况
                        number.append(t)      #把删除的加回去
                        number = queue(number)    #排序是为了下次循环能正确遍历下一个数
                break #得到一次结果为20的就终止这次循环,不用再往下遍历了,进行下一次

if __name__ == '__main__':
    ###下面两句是用于自己输入数组的,用空格隔开
    print("请输入数组:")
    # 下面一步是利用map将输入的[1 2 3 4]分成[1,2,3,4],但是出来的是map类型,
    # 所以要转成list型,float是把里面的数按那种类型分,可以是int,这里是由于可以输入浮点型
    num = list(map(float, input().split()))
    n = float(input('请输入:'))
    ReNumber = [] #存储已经求和的数组

    f = open("plus.txt", "w") #清空文本,前面函数用的a,这次w,作用就是第二次运行代码清空文件夹
    f.close()

    QuickSort(num) #排序
    FNN(n)
    for i in ReNumber: #最后将结果写文件
        WriteFile(i)
        print(i)

运行结果:

原文链接: https://www.cnblogs.com/hecong/p/13174467.html

猜你喜欢

转载自www.cnblogs.com/zqm-sau/p/13180251.html
今日推荐