暴力求解算法,组合与全排列

        一个星期的时间,学习了暴力求解法。虽然还是有些缺陷,不过可以感觉到自己的进步,现写一个博客来总结。

        暴力求解就是,枚举所有可能的情况,然后再一个个比对是否是正确的解,当数据量较小的时候可以用。洛谷的官方题单--暴力求解中,全排列和组合题占大多数,这个就是个模板

首先p1157 组合的输出

 上代码

 对于当前每一个数,我都先考虑将它选取(help列表储存),然后回溯到这一层的时候就不选取(在help列表中删除)再继续往下递归。然后当help列表的长度达到目标值时,就得到了其中一组组合。也就是每一个数都有两种情况,即选取和不选取。

再一个p1706 全排列的问题

 直接上代码

         全排列简单来说就是,每一个数都要在每一个位置出现一次,也就是,第i层递归里面,每一个数都要当一次第i个数。

        于是乎,每一层递归都要一次循环遍历。然后用一个seen列表记录这个数是否用过,避免重复使用,如果没用过,那么就用掉,进入下一层递归。回溯到这个数的时候,这个数在这个位置的所有情况已经被遍历完毕,可以跟着循环去到下一个数了。

当面临一些较大的数据,单纯的暴力组合排列会超时,所以我们需要一些玄学思考

p1618

 上代码

a,b,c=map(int,input().split())
num=[]
seen=[0]*9
help=[]

nums1=[]
ans=0
def func(index):  #得到组合
    global help
    if 9-index+len(help)+1<3:
        return
    if len(help)==3:
        num.append(tuple(help))
        return
    help.append(index)
    func(index+1)
    help.pop()
    func(index+1)
def quan(seen,vals):  #得到全排列
    if len(help)==3:
        nums.append(tuple(help))
        return
    for i in range(3):
        if seen[i]==1:
            continue
        seen[i]=1
        help.append(vals[i])
        quan(seen,vals)
        help.pop()
        seen[i]=0
func(1)  #得到组合,储存

for i in num:
    seen=[0]*3
    quan(seen,i)  #得到全排列储存
del num
nums=[]
for i in nums:  #全排列转化为数字
    sum=0
    for j  in i:
        sum=sum*10+j
    nums1.append(sum)
for i in nums1:
    temp=[]
    m=i*b/a
    n=i*c/a
    if m in nums1 and n in nums1:  #有重复数字就无效
        flag=1
        for j in range(3):
            if str(m).count(str(i)[j])!=0:
                flag=0
                break
            if str(m).count(str(n)[j])!=0:
                flag=0
                break
            if str(n).count(str(m)[j])!=0:
                flag=0
                break
            if str(n).count(str(i)[j])!=0:
                flag=0
                break
            if str(i).count(str(m)[j])!=0:
                flag=0
                break
            if str(i).count(str(n)[j])!=0:
                flag=0
                break
        if flag==1:
            ans=1
            print(i,int(m),int(n))

if ans==1:
    print("No!!!")

代码有些丑。。。巨丑无比

        如果单纯的全排列,9个数字的全排列必然超时,这时我们只需要找到9个数字中,三个数字的全排列,然后再按照比例去找后面两个是否符合条件。

除了排列组合,还有一些枚举的题目

p1217 回文质数

 因为数据最大高达一亿,所以枚举接判断直接g

这个时候,只能选择生成回文数

"""
洛谷p1217
此题数据大,就算你知道遍历的步进为2,就算知道偶数位不为素数也没用,足足一亿次,所以换一种思路,生成回文串,再判断是否质数
"""
import math
#
a,e=map(int,input().split())
mid=0
zuhe=[]
help=[]
quanpailie=[]
def isprime(num):
    for i in range(2,int(math.sqrt(num))+1):
        if num%i==0:
            return False
    return True
def hui3():
    for i in range(1,10,2):
        for mid in range(0,10):
            num=100*i+mid*10+i
            if num < a:
                continue
            if num > e:
                return
            if isprime(num):
                print(num)

def hui5():
    for i in range(1,10,2):
        for j in range(0,10):
            for mid in range(0,10):
                num=10000*i+1000*j+100*mid+10*j+i
                if num>e:
                    return
                if num < a:
                    continue
                if isprime(num):
                    print(num)

def hui7():
    for i in range(1,10,2):
        for j in range(0,10):
            for k in range(0,10):
                for mid in range(0,10):
                    num=1000000*i+100000*j+10000*k+1000*mid+100*k+10*j+i
                    if num>e:
                        return
                    if num<a:
                        continue
                    if isprime(num):
                       print(num)

if a==5:
    print(5)
if a<=7:
    print(7)
if a<=11:
    print(11)
hui3()
hui5()
hui7()

根据某玄学,偶数位数肯定不是素数,

两位数的素数只有11,然后生成位数分别为3 5 7 的素数。

p2392 

 这个题,就是把时间分为两组,让两组差的绝对值最小

s1,s2,s3,s4=map(int,input().split())
nums1=list(map(int,input().split()))
nums2=list(map(int,input().split()))
nums3=list(map(int,input().split()))
nums4=list(map(int,input().split()))


def func(nums,l,r,index):#本质就是把数组分成两组,然后使两组差的绝对值最小
    if index==len(nums):
        return abs(l-r)+min(l,r)
    return min(func(nums,l+nums[index],r,index+1),func(nums,l,r+nums[index],index+1))


print(func(nums1,0,0,0)+func(nums2,0,0,0)+func(nums3,0,0,0)+func(nums4,0,0,0))

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值