当前位置:   article > 正文

蓝桥杯刷题总结----第四周_如果字符串的个数n为52,则输出用小弱洗牌法洗牌后的序列,每个字符串后都有一个空

如果字符串的个数n为52,则输出用小弱洗牌法洗牌后的序列,每个字符串后都有一个空

一.夺宝奇兵

在一座山上,有很多很多珠宝,它们散落在山底通往山顶的每条道路上,不同道路上的珠宝的数目也各不相同.下图为一张藏宝地图:
7
3  8
8  1  0
2  7  4  4
4  5  2  6  5
”夺宝奇兵”从山下出发,到达山顶,如何选路才能得到最多的珠宝呢?在上图所示例子中,按照5-> 7-> 8-> 3-> 7的顺序,将得到最大值30

思路:简单的动态规划

  1. n=eval(input())
  2. G=[]
  3. for _ in range(n):
  4. G.append(list(map(eval,input().split())))
  5. dp=[[0 for i in range(n)] for j in range(n)]
  6. for i in range(n):
  7. dp[0][i]=G[0][0]
  8. for i in range(1,n):
  9. for j in range(n):
  10. if j>=len(G[i]):
  11. break
  12. else:
  13. if j==0:
  14. dp[i][j]=G[i][j]+dp[i-1][j]
  15. else:
  16. dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+G[i][j]
  17. print(max([dp[n-1][j] for j in range(n)]))

二.实数相加

两行字符串,每行都是一个合法的实数。合法的意思是指:  整数部分的值如果大于零,则最高位数字必定大于零.  如果整数部分的值为零,则整数部分只有一个零.  小数部分尾部可以有任意多的零.  可以没有小数部分,  此时也没有小数点.  如果有小数点,  则至少需要有一位小数部分,  且允许是零. 

输入的实数满足如下要求:  (1)  小数点前的整数部分最多100位,(2)  小数点后的小数部分最多100位

思路:利用python的decimal保存小数,我使用字符串计算时会出现各种各样的错误

  1. from decimal import *
  2. getcontext().prec=1000
  3. a=Decimal(input().strip())
  4. b=Decimal(input().strip())
  5. print(a+b)

 三.开灯游戏

有9盏灯与9个开关,编号都是1~9。
每个开关能控制若干盏灯,按下一次会改变其控制的灯的状态(亮的变成不亮,不亮变成亮的)。
具体如下:
第一个开关控制第二,第四盏灯;
第二个开关控制第一,第三,第五盏灯;
第三个开关控制第二,第六盏灯;
第四个开关控制第一,第五,第七盏灯;
第五个开关控制第二,第四,第六,第八盏灯;
第六个开关控制第三,第五,第九盏灯;
第七个开关控制第四,第八盏灯;
第八个开关控制第五,第七,第九盏灯;
第九个开关控制第六,第八盏灯。
开始时所有灯都是熄灭的,开关是关闭着的。要求按下若干开关后,使得只有4盏灯亮着。

思路:利用kaiguan列表保存控制的开关数,再dfs回溯

  1. state=[1,0,0,0,0,0,0,0,0,0]
  2. kaiguan=[[2,4],[1,3,5],[2,6],[1,5,7],[2,4,6,8],[3,5,9],[4,8],[5,7,9],[6,8]]
  3. ans=[]
  4. def dfs(s):
  5. global ans,state,kaiguan
  6. if len(s)==9:
  7. if sum(state)==5:
  8. ans.append(s)
  9. # print(state)
  10. return
  11. else:
  12. dfs(s+'0')
  13. for i in kaiguan[len(s)]:
  14. state[i]=(state[i]+1)%2
  15. dfs(s+'1')
  16. for i in kaiguan[len(s)]:
  17. state[i]=(state[i]+1)%2
  18. dfs('')
  19. for i in ans:
  20. print(i)

四.师座操作系统

师座这天在程序设计课上学了指针和结构体以后,觉得自己可以轻松的写出操作系统,为了打败大微软帝国,他给这个系统起了个响亮的名字“师座操作系统”,你是师座手下的首席架构师,被要求写这个操作系统的文件系统部分,要求如下:
这个文件系统有的所有文件都有一个独一无二的文件名,除此之外分为两类文件,一类文件是数据存储文件,它可以存储一个字符串信息,另一类文件是快捷方式,它会指向另一个文件,有可能是数据块也有可能是快捷方式。
.这个文件系统支持3条命令:
1.创建命令:create  < FileName>   < FileType>   < FileInfo>
这个命令的意思是,创建一个文件名为< FileName> ,文件类型为< FileType> ,文件信息  为< FileInfo> ,文件类型为0或者1,0表示数据块,1表示快捷方式,如果是数据块,那么< FileInfo> 表示储存  的字符串,如果这是一个快捷方式,< FileInfo> 表示指向的文件的名称,如果当前已存在名为< FileName> 的文件,  则更新这个文件的信息。
.2.打开命令:open  < FileName>
这个命令是打开文件名为< FileName> 的文件,如果这是一个快捷方式,则会打开这个快捷方式指向的文件,直到打开一个数据块时,显示这个数据块储存的信息并换行。
.3.退出命令:exit
得到这个命令以后,你的程序需要安全终止。

  1. file_dic=dict()
  2. while True:
  3. order=list(input().split())
  4. if order[0]=='exit':
  5. break
  6. elif order[0]=='create':
  7. if order[2]=='0':
  8. file_dic[order[1]]=[order[3],0]
  9. else:
  10. file_dic[order[1]]=[order[3],1]
  11. else:
  12. while file_dic[order[1]][1]!=0:
  13. order[1]=file_dic[order[1]][0]
  14. print(file_dic[order[1]][0])

五.打水问题

N个人要打水,有M个水龙头,第i个人打水所需时间为Ti,请安排一个合理的方案使得所有人的等待时间之和尽量小。
提示
一种最佳打水方案是,将N个人按照Ti从小到大的顺序依次分配到M个龙头打水。
例如样例中,Ti从小到大排序为1,2,3,4,5,6,7,将他们依次分配到3个龙头,则去龙头一打水的为1,4,7;去龙头二打水的为2,5;去第三个龙头打水的为3,6。
第一个龙头打水的人总等待时间  =  0  +  1  +  (1  +  4)  =  6
第二个龙头打水的人总等待时间  =  0  +  2  =  2
第三个龙头打水的人总等待时间  =  0  +  3  =  3
所以总的等待时间  =  6  +  2  +  3  =  11

思路:按顺序排好分组,让时间最短的先打,再求前缀和

  1. n,m=map(eval,input().split())
  2. t=list(map(eval,input().split()))
  3. t.sort()
  4. group=[[] for _ in range(m)]
  5. for i in range(n):
  6. group[i%m].append(t[i])
  7. ans=0
  8. for g in group:
  9. temp_sum=0
  10. for i in range(len(g)-1):
  11. temp_sum+=g[i]
  12. ans+=temp_sum
  13. print(ans)

六.最小乘积

给两组数,各n个。
请调整每组数的排列顺序,使得两组数据相同下标元素对应相乘,然后相加的和最小。要求程序输出这个最小值。
例如两组数分别为:1  3  -5和-2  4  1
那么对应乘积取和的最小值应为:
(-5)  *  4  +  3  *  (-2)  +  1  *  1  =  -25

  1. n=eval(input())
  2. for _ in range(n):
  3. l=eval(input())
  4. num1=list(map(eval,input().split()))
  5. num2 = list(map(eval, input().split()))
  6. num1.sort()
  7. num2.sort(reverse=True)
  8. ans=0
  9. for i in range(l):
  10. ans+=num1[i]*num2[i]
  11. print(ans)

七.数的划分

一个正整数可以划分为多个正整数的和,比如n=3时:
3;1+2;1+1+1;
共有三种划分方法。
给出一个正整数,问有多少种划分方法。

思路:类比球放入盒子的排列组合,每个盒子不空,dp[i][j]表示i个球放入j个盒子,可以分为两种情况,每个盒子至少有两个球和最少有一个盒子只有一个球,所以dp[i][j]=dp[i-j][j]+dp[i-1][j-1]

  1. n=eval(input())
  2. dp=[[0 for _ in range(n)] for __ in range(n)]
  3. for i in range(n):
  4. dp[i][0]=1
  5. dp[i][i]=1
  6. for i in range(2,n):#i个球放入j个盒子 注意下标与实际问题的关系,要适当加一,以免出错
  7. for j in range(1,i):
  8. dp[i][j]=dp[i-j-1][j]+dp[i-1][j-1]#注意最后要减一 i-j-1
  9. print(sum(dp[n-1]))

八.摆花

小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆。通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号。为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时同一种花放在一起,且不同种类的花需按标号的从小到大的顺序依次摆列。
试编程计算,一共有多少种不同的摆花方案。

样例说明:有2种摆花的方案,分别是(1,1,1,2),  (1,1,2,2)。括号里的1和2表示两种花,比如第一个方案是前三个位置摆第一种花,第四个位置摆第二种花。

思路:使用动态规划dp[i][j]表示当前用了i种花,用了j盆,遍历所有可能的情况
 

  1. n,m=map(eval,input().split())
  2. nums=list(map(eval,input().split()))
  3. dp=[[0 for i in range(m+1)] for j in range(n+1)]
  4. for i in range(1,nums[0]+1):
  5. dp[1][i]=1
  6. for i in range(n+1):
  7. dp[i][0]=1
  8. for i in range(2,n+1):
  9. for j in range(1,m+1):
  10. for k in range(nums[i-1]+1):
  11. if j<k:
  12. continue
  13. dp[i][j]+=dp[i-1][j-k]
  14. print(dp[n][m]%1000007)

九.埃式筛法求素数

给定区间[L,  R]  ,  请计算区间中素数的个数。

  1. from math import *
  2. n,m=map(eval,input().split())
  3. ans=[True for i in range(1000001)]
  4. a=[True for i in range(1000001)]
  5. a[1]=False
  6. i=2
  7. while i*i<=m:
  8. if a[i]:
  9. j=2
  10. while i*j<sqrt(m):
  11. a[i*j]=False
  12. j+=1
  13. k=ceil(n/i)
  14. while k*i<=m:
  15. if k!=1:
  16. ans[k*i-n]=False
  17. k+=1
  18. i+=1
  19. ans=ans[:m-n+1]
  20. print(ans.count(True))

十.排列式

7254是一个不寻常的数,因为它可以表示为7254  =  39  x  186,这个式子中1~9每个数字正好出现一次
输出所有这样的不同的式子(乘数交换被认为是相同的式子)
结果小的先输出;结果相同的,较小的乘数较小的先输出。

思路:暴力遍历两个乘数,求出乘积后利用集合分别判断三个数是否满足要求

  1. def already_have(num,num_set):
  2. while num:
  3. if num%10 in num_set or num%10==0:
  4. return False
  5. else:
  6. num_set.add(num%10)
  7. num//=10
  8. return True
  9. ans=[]
  10. for i in range(2,99):
  11. for j in range(111,4999):
  12. if i*j<1000:
  13. continue
  14. else:
  15. set_num=set()
  16. if already_have(i,set_num) and already_have(j,set_num) and already_have(i*j,set_num) and len(set_num)==9:
  17. ans.append([i*j,i,j])
  18. ans.sort(key=lambda x:x[0])
  19. for i in ans:
  20. print("{} = {} x {}".format(i[0],i[1],i[2]))

十一.棋盘多项式

八皇后问题是在棋  盘上放皇后,互相不攻击,求方案。变换一下棋子,还可以有八车问题,八马问题,八兵问题,八王问题,注意别念反。在这道题里,棋子换成车,同时棋盘也得  换,确切说,是进行一些改造。比如现在有一张n*n的棋盘,我们在一些格子上抠几个洞,这些洞自然不能放棋子了,会漏下去的。另外,一个车本来能攻击和它  的同行同列。现在,你想想,在攻击的过程中如果踩到一个洞,便会自取灭亡。故,车的攻击范围止于洞。
此题,给你棋盘的规模n,以及挖洞情况,求放k个车的方案数(k从0到最多可放车数)

思路:利用邻接矩阵的不同值代表不同状态,0表示阻挡,1表示空位,2表示受到其他皇后的影响而不能放置,其中2可以叠加到4,这样回溯直接减2就可以恢复原来的状态
 

  1. n=eval(input())
  2. G=[]
  3. for _ in range(n):
  4. G.append(list(map(eval,input().split())))
  5. ans=[0 for _ in range(64)]
  6. def dfs(i,j,num):
  7. global n,ans,G
  8. ans[num-1]+=1
  9. G[i][j]=2
  10. temp_i=n
  11. temp_j=n
  12. for ii in range(i+1,n):
  13. if G[ii][j]==0:
  14. temp_i=ii
  15. break
  16. G[ii][j]+=2
  17. for jj in range(j+1,n):
  18. if G[i][jj]==0:
  19. temp_j=jj
  20. break
  21. G[i][jj]+=2
  22. for ii in range(i,n):
  23. for jj in range(n):
  24. if ii==i and jj<=j:
  25. continue
  26. if G[ii][jj]==1:
  27. dfs(ii,jj,num+1)
  28. G[i][j]=1
  29. for ii in range(i+1,temp_i):
  30. G[ii][j]-=2
  31. for jj in range(j+1,temp_j):
  32. G[i][jj]-=2
  33. return
  34. for i in range(n):
  35. for j in range(n):
  36. if G[i][j]==1:
  37. dfs(i,j,1)
  38. for i in ans:
  39. if i==0:
  40. break
  41. print(i)

十二.洗牌

小弱T在闲暇的时候会和室友打扑克,输的人就要负责洗牌。虽然小弱T不怎么会洗牌,但是他却总是输。
渐渐地小弱T发现了一个规律:只要自己洗牌,自己就一定会输。所以小弱T认为自己洗牌不够均匀,就独创了一种小弱洗牌法。
小弱洗牌法是这样做的:先用传统洗牌法将52张扑克牌(1到K各四张,除去大小王)打乱,放成一堆,然后每次从牌堆顶层拿一张牌。如果这张牌的大小是  P(1到K的大小分别为1到13),那么就把这张牌插入到当前手中第P张牌的后面。如果当前手中不足P张牌,那么就把这张牌放在最后。
现在给你一对已经被打乱的牌,请你用小弱洗牌法进行洗牌,然后输出最后生成的序列。
注意:小弱可能在第一次洗牌时弄丢了某些牌,这时请你输出一个-1来提醒他牌的数目不够。

思路:简单的模拟

  1. pai=[]
  2. while True:
  3. try:
  4. nums=list(input().split())
  5. pai.append(nums)
  6. except:
  7. break
  8. dui=[]
  9. for i in range(len(pai)):
  10. for j in range(len(pai[i])):
  11. dui.append(pai[i][j])
  12. if len(dui)<52:
  13. print(-1)
  14. else:
  15. dic_num=dict()
  16. dic_num['1']=1
  17. dic_num['2']=2
  18. dic_num['3'] = 3
  19. dic_num['4'] = 4
  20. dic_num['5'] = 5
  21. dic_num['6'] = 6
  22. dic_num['7'] = 7
  23. dic_num['8'] = 8
  24. dic_num['9'] = 9
  25. dic_num['10'] = 10
  26. dic_num['J'] = 11
  27. dic_num['Q'] = 12
  28. dic_num['K'] = 13
  29. ans=[]
  30. for i in dui:
  31. if dic_num[i]>len(ans):
  32. ans.append(i)
  33. else:
  34. ans.insert(dic_num[i],i)
  35. for i in ans:
  36. print(i,end=' ')
  37. print()

十三.现代诗如蚯蚓

现代诗如蚯蚓
断成好几截都不会死
字符串断成好几截
有可能完全一样
请编写程序
输入字符串
输出该字符串最多能断成多少截完全一样的子串

样例说明
最多能断成四个”abc”,也就是abc重复四遍便是原串
同时也能断成两个”abcabc”
最坏情况是断成一个原串”abcabcabcabc” 

思路:直接从头开始遍历,求最小的长度

  1. n=input()
  2. num=len(n)
  3. flag=True
  4. for i in range(1,num//2+1):
  5. if n[:i]*(num//i) == n:
  6. print(num//i)
  7. flag=False
  8. break
  9. if flag:
  10. print(1)

十四.种树

A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门  得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树就可以得到这Ai的美观度。但由于A城市土壤  肥力欠佳,两棵树决不能种在相邻的位置(i号位置和i+1号位置叫相邻位置。值得注意的是1号和n号也算相邻位置!)。

最终市政府给园林部门提供了m棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将m棵树苗全部种上,给出无解信息。

思路:注意是环形的,利用flag记录第一个节点是否种树

  1. n,m=map(eval,input().split())
  2. nums=list(map(eval,input().split()))
  3. ans=-float('inf')
  4. def dfs(i,temp_ans,temp_m,flag):
  5. global n,m,ans,nums
  6. temp_ans+=nums[i]
  7. if temp_m==m:
  8. if temp_ans>ans:
  9. ans=temp_ans
  10. else:
  11. if i+2<n:
  12. for ii in range(i+2,n):
  13. if ii ==n-1 and flag:
  14. break
  15. dfs(ii,temp_ans,temp_m+1,flag)
  16. for i in range(n):
  17. if i==0:
  18. dfs(i,0,1,True)
  19. else:
  20. dfs(i,0,1,False)
  21. if ans !=-float('inf'):
  22. print(ans)
  23. else:
  24. print('Error!')

十五.线段和点

有n个点和m个区间,点和区间的端点全部是整数,对于点a和区间[b,c],若a> =b且a< =c,称点a满足区间[b,c]。
求最小的点的子集,使得所有区间都被满足。

  1. n, m = map(eval, input().split())
  2. A = []
  3. for i in range(n):
  4. A.append(eval(input()))
  5. A.sort() # A点集排序
  6. B = []
  7. for i in range(m):
  8. B.append(list(map(int, input().split())))
  9. B = sorted(B, key=lambda x: (x[0], -x[1])) # B区间排序
  10. start = 0 # 定位推进区间
  11. ans = 0
  12. while start < m:
  13. max_num = 0
  14. max_index = 0
  15. for i in range(len(A)): # 寻找使得start最接近m的点
  16. temp = start
  17. while temp < m:
  18. if B[temp][0] <= A[i] <= B[temp][1]:
  19. temp = temp + 1
  20. else:
  21. break
  22. if temp > max_num: # 记录该点的下标和区间
  23. max_num = temp
  24. max_index = i
  25. start = max_num # 更新start
  26. del (A[max_index]) # 删除该点
  27. ans = ans + 1
  28. if len(A) == 0:
  29. break
  30. if start == m:
  31. print(ans)
  32. else:
  33. print(-1)

十六.超级玛丽

大家都知道" 超级玛丽" 是一个很善于跳跃的探险家,他的拿手好戏是跳跃,但它一次只能向前跳一步或两步。有一次,他要经过一条长为n的羊肠小道,小道中有m个陷阱,这些陷阱都位于整数位置,分别是a1,a2,....am,陷入其中则必死无疑。显然,如果有两个挨着的陷阱,则玛丽是无论如何也跳过不去的。
现在给出小道的长度n,陷阱的个数及位置。求出玛丽从位置1开始,有多少种跳跃方法能到达胜利的彼岸(到达位置n)。

思路:类似于爬楼梯

  1. n,m=map(eval,input().split())
  2. trap=set(map(eval,input().split()))
  3. dp=[1 for i in range(n)]
  4. for i in range(m):
  5. j=trap.pop()
  6. if j<=n:
  7. dp[j-1]=0
  8. for i in range(2,n):
  9. if dp[i]==0:
  10. continue
  11. else:
  12. dp[i]=dp[i-1]+dp[i-2]
  13. print(dp[n-1])

十七.质数的后代

在上一季里,曾提到过质数的孤独,其实从另一个角度看,无情隔膜它们的合数全是质数的后代,因为合数可以由质数相乘结合而得。
如果一个合数由两个质数相乘而得,那么我们就叫它是质数们的直接后代。现在,给你一系列自然数,判断它们是否是质数的直接后代。

思路:根据数据范围先求出所有的质数,再逐个判断

  1. T=eval(input())
  2. def is_prime(num):
  3. if num==2:
  4. return True
  5. else:
  6. for i in range(2,int(num**0.5)+1):
  7. if num%i==0:
  8. return False
  9. return True
  10. prime_list=[]
  11. for i in range(2,100000):
  12. if is_prime(i):
  13. prime_list.append(i)
  14. def is_son(num):
  15. global prime_list
  16. if num%2==0:
  17. if is_prime(num//2):
  18. return True
  19. return False
  20. elif num==1:
  21. return False
  22. else:
  23. for i in prime_list:
  24. if i>num:
  25. break
  26. elif num%i==0 and num//i in prime_list:
  27. return True
  28. return False
  29. for _ in range(T):
  30. if is_son(eval(input())):
  31. print("Yes")
  32. else:
  33. print("No")

十八.铺地毯

为了准备一个学生节,组织者在会场的一片矩形区域(可看做是平面直角坐标
系的第一象限)铺上一些矩形地毯。一共有n  张地毯,编号从1  到n。现在将这些地毯按照
编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。
地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形
地毯边界和四个顶点上的点也算被地毯覆盖。
 

  1. num=eval(input())
  2. capmap=[]
  3. for _ in range(num):
  4. capmap.append(list(map(eval,input().split())))
  5. loc=list(map(eval,input().split()))
  6. flag=False
  7. for i in range(num-1,-1,-1):
  8. if capmap[i][0]<=loc[0] and capmap[i][0]+capmap[i][2]>=loc[0]:
  9. if capmap[i][1]<=loc[1] and capmap[i][1]+capmap[i][3]>=loc[1]:
  10. print(i+1)
  11. flag=True
  12. break
  13. if not flag:
  14. print(-1)

十九.项链

由  n(1≤n≤100)  个珠子组成的一个项链,珠子有红、蓝、白三种颜色,各种颜色的珠子的安排顺序由键盘输入的字符串任意给定。蓝色用小写字母b表示,红色用小写字母r表示,  白色用小写字母w表示.
假定从项链的某处将其剪断,把它摆成一条直线。先从左端向右收集同色珠子,遇到第一个异色珠子时停止.  收集过程中,  白色是一种特殊颜色,  既可以看成红色也可以看成蓝色。然后再从剩余珠子的右端向左重复上述过程。
例如:对下图一所示的项链,  如果从图一中标记的位置0处剪断,  则按顺时针顺序得到wbbbwwrrbwbrrwb(如图二所示)。这时从左端开始收集可以得到wbbbww,    共6个珠子;然后从剩余珠子右端开始收集得到wb,共2个珠子。这种剪法共可收集到6+2=8个珠子。  如果从图一中标记的位置4处剪断,  则按顺时针顺序得到wwrrbwbrrwbwbbb(如图二所示)。这时从左端收集可以得到wwrr,共4个珠子;  然后从剩余珠子右端收集可以得到wbwbbb,共6个珠子。这种剪法共可收集到4+6=10个珠子。
要求:  在项链中选择合适的剪断位置,  使得从左右两端收集到的珠子数目之和最大,输出收集到的珠子数的最大值M。

思路:从两边直接判断

  1. string=input().strip()
  2. ans=0
  3. for i in range(len(string)):
  4. temp=0
  5. temp_i=0
  6. j=i
  7. while True:
  8. if string[j]=='b':
  9. if temp_i==0:
  10. temp_i=1
  11. elif temp_i==2:
  12. break
  13. elif string[j]=='r':
  14. if temp_i==0:
  15. temp_i=2
  16. elif temp_i==1:
  17. break
  18. temp+=1
  19. j=(j+1)%len(string)
  20. j=(i-1)%len(string)
  21. temp_i=0
  22. while True:
  23. if string[j]=='b':
  24. if temp_i==0:
  25. temp_i=1
  26. elif temp_i==2:
  27. break
  28. elif string[j]=='r':
  29. if temp_i==0:
  30. temp_i=2
  31. elif temp_i==1:
  32. break
  33. temp+=1
  34. j=(j-1)%len(string)
  35. if temp>ans:
  36. ans=temp
  37. ii=i
  38. print(ans)

二十.密码锁

你获得了一个据说是古代玛雅人制作的箱子。你非常想打开箱子看看里面有什么东西,但是不幸的是,正如所有故事里一样,神秘的箱子出现的时候总是会挂着神秘的锁。
这个锁上面看起来有  N  个数字,它们排成一排,并且每个数字都在  0  到  2  之间。你发现你可以通过锁上的机关来交换相邻两个数字的顺序。比如,如果原来有  5  个数字  02120,在一次交换以后你就可以得到  20120,01220,02210  或者  02102。
根据你所搜集的情报,这个锁在上面存在某连续四个数字是“2012”的时候会自动打开。现在,你需要计算一下,你至少需要进行多少次交换操作才能打开这把锁?
对样例的解释
把前两个数字交换以后,锁上的数字是  20120,其中存在连续四个数字2,  0,  1,  2,因此锁会打开。

思路:简单的bfs

  1. from collections import *
  2. n=eval(input())
  3. string=input()
  4. q=deque()
  5. q.append([string,0,-1])
  6. if string.count('1')<1 or string.count('2')<2 or string.count('0')<1:
  7. print(-1)
  8. else:
  9. num_dict=defaultdict(int)
  10. while len(q):
  11. temp_string, step, index = q.popleft()
  12. if '2012' in temp_string:
  13. print(step)
  14. break
  15. for i in range(n - 1):
  16. if i == index:
  17. continue
  18. else:
  19. my_temp_string = temp_string[:i] + temp_string[i + 1] + temp_string[i] + temp_string[i + 2:]
  20. if num_dict[my_temp_string]==0:
  21. num_dict[my_temp_string]=1
  22. q.append([my_temp_string, step + 1, i])

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/514587
推荐阅读
相关标签
  

闽ICP备14008679号