一个星期的时间,学习了暴力求解法。虽然还是有些缺陷,不过可以感觉到自己的进步,现写一个博客来总结。
暴力求解就是,枚举所有可能的情况,然后再一个个比对是否是正确的解,当数据量较小的时候可以用。洛谷的官方题单--暴力求解中,全排列和组合题占大多数,这个就是个模板
首先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))