在一座山上,有很多很多珠宝,它们散落在山底通往山顶的每条道路上,不同道路上的珠宝的数目也各不相同.下图为一张藏宝地图:
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
”夺宝奇兵”从山下出发,到达山顶,如何选路才能得到最多的珠宝呢?在上图所示例子中,按照5-> 7-> 8-> 3-> 7的顺序,将得到最大值30
思路:简单的动态规划
n=eval(input())
G=[]
for _ in range(n):
G.append(list(map(eval,input().split())))
dp=[[0 for i in range(n)] for j in range(n)]
for i in range(n):
dp[0][i]=G[0][0]
for i in range(1,n):
for j in range(n):
if j>=len(G[i]):
break
else:
if j==0:
dp[i][j]=G[i][j]+dp[i-1][j]
else:
dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+G[i][j]
print(max([dp[n-1][j] for j in range(n)]))
两行字符串,每行都是一个合法的实数。合法的意思是指: 整数部分的值如果大于零,则最高位数字必定大于零. 如果整数部分的值为零,则整数部分只有一个零. 小数部分尾部可以有任意多的零. 可以没有小数部分, 此时也没有小数点. 如果有小数点, 则至少需要有一位小数部分, 且允许是零.
输入的实数满足如下要求: (1) 小数点前的整数部分最多100位,(2) 小数点后的小数部分最多100位
思路:利用python的decimal保存小数,我使用字符串计算时会出现各种各样的错误
from decimal import *
getcontext().prec=1000
a=Decimal(input().strip())
b=Decimal(input().strip())
print(a+b)
有9盏灯与9个开关,编号都是1~9。
每个开关能控制若干盏灯,按下一次会改变其控制的灯的状态(亮的变成不亮,不亮变成亮的)。
具体如下:
第一个开关控制第二,第四盏灯;
第二个开关控制第一,第三,第五盏灯;
第三个开关控制第二,第六盏灯;
第四个开关控制第一,第五,第七盏灯;
第五个开关控制第二,第四,第六,第八盏灯;
第六个开关控制第三,第五,第九盏灯;
第七个开关控制第四,第八盏灯;
第八个开关控制第五,第七,第九盏灯;
第九个开关控制第六,第八盏灯。
开始时所有灯都是熄灭的,开关是关闭着的。要求按下若干开关后,使得只有4盏灯亮着。
思路:利用kaiguan列表保存控制的开关数,再dfs回溯
state=[1,0,0,0,0,0,0,0,0,0]
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]]
ans=[]
def dfs(s):
global ans,state,kaiguan
if len(s)==9:
if sum(state)==5:
ans.append(s)
# print(state)
return
else:
dfs(s+'0')
for i in kaiguan[len(s)]:
state[i]=(state[i]+1)%2
dfs(s+'1')
for i in kaiguan[len(s)]:
state[i]=(state[i]+1)%2
dfs('')
for i in ans:
print(i)
师座这天在程序设计课上学了指针和结构体以后,觉得自己可以轻松的写出操作系统,为了打败大微软帝国,他给这个系统起了个响亮的名字“师座操作系统”,你是师座手下的首席架构师,被要求写这个操作系统的文件系统部分,要求如下:
这个文件系统有的所有文件都有一个独一无二的文件名,除此之外分为两类文件,一类文件是数据存储文件,它可以存储一个字符串信息,另一类文件是快捷方式,它会指向另一个文件,有可能是数据块也有可能是快捷方式。
.这个文件系统支持3条命令:
1.创建命令:create < FileName> < FileType> < FileInfo>
这个命令的意思是,创建一个文件名为< FileName> ,文件类型为< FileType> ,文件信息 为< FileInfo> ,文件类型为0或者1,0表示数据块,1表示快捷方式,如果是数据块,那么< FileInfo> 表示储存 的字符串,如果这是一个快捷方式,< FileInfo> 表示指向的文件的名称,如果当前已存在名为< FileName> 的文件, 则更新这个文件的信息。
.2.打开命令:open < FileName>
这个命令是打开文件名为< FileName> 的文件,如果这是一个快捷方式,则会打开这个快捷方式指向的文件,直到打开一个数据块时,显示这个数据块储存的信息并换行。
.3.退出命令:exit
得到这个命令以后,你的程序需要安全终止。
file_dic=dict()
while True:
order=list(input().split())
if order[0]=='exit':
break
elif order[0]=='create':
if order[2]=='0':
file_dic[order[1]]=[order[3],0]
else:
file_dic[order[1]]=[order[3],1]
else:
while file_dic[order[1]][1]!=0:
order[1]=file_dic[order[1]][0]
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
思路:按顺序排好分组,让时间最短的先打,再求前缀和
n,m=map(eval,input().split())
t=list(map(eval,input().split()))
t.sort()
group=[[] for _ in range(m)]
for i in range(n):
group[i%m].append(t[i])
ans=0
for g in group:
temp_sum=0
for i in range(len(g)-1):
temp_sum+=g[i]
ans+=temp_sum
print(ans)
给两组数,各n个。
请调整每组数的排列顺序,使得两组数据相同下标元素对应相乘,然后相加的和最小。要求程序输出这个最小值。
例如两组数分别为:1 3 -5和-2 4 1
那么对应乘积取和的最小值应为:
(-5) * 4 + 3 * (-2) + 1 * 1 = -25
n=eval(input())
for _ in range(n):
l=eval(input())
num1=list(map(eval,input().split()))
num2 = list(map(eval, input().split()))
num1.sort()
num2.sort(reverse=True)
ans=0
for i in range(l):
ans+=num1[i]*num2[i]
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]
n=eval(input())
dp=[[0 for _ in range(n)] for __ in range(n)]
for i in range(n):
dp[i][0]=1
dp[i][i]=1
for i in range(2,n):#i个球放入j个盒子 注意下标与实际问题的关系,要适当加一,以免出错
for j in range(1,i):
dp[i][j]=dp[i-j-1][j]+dp[i-1][j-1]#注意最后要减一 i-j-1
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盆,遍历所有可能的情况
n,m=map(eval,input().split())
nums=list(map(eval,input().split()))
dp=[[0 for i in range(m+1)] for j in range(n+1)]
for i in range(1,nums[0]+1):
dp[1][i]=1
for i in range(n+1):
dp[i][0]=1
for i in range(2,n+1):
for j in range(1,m+1):
for k in range(nums[i-1]+1):
if j
给定区间[L, R] , 请计算区间中素数的个数。
from math import *
n,m=map(eval,input().split())
ans=[True for i in range(1000001)]
a=[True for i in range(1000001)]
a[1]=False
i=2
while i*i<=m:
if a[i]:
j=2
while i*j
7254是一个不寻常的数,因为它可以表示为7254 = 39 x 186,这个式子中1~9每个数字正好出现一次
输出所有这样的不同的式子(乘数交换被认为是相同的式子)
结果小的先输出;结果相同的,较小的乘数较小的先输出。
思路:暴力遍历两个乘数,求出乘积后利用集合分别判断三个数是否满足要求
def already_have(num,num_set):
while num:
if num%10 in num_set or num%10==0:
return False
else:
num_set.add(num%10)
num//=10
return True
ans=[]
for i in range(2,99):
for j in range(111,4999):
if i*j<1000:
continue
else:
set_num=set()
if already_have(i,set_num) and already_have(j,set_num) and already_have(i*j,set_num) and len(set_num)==9:
ans.append([i*j,i,j])
ans.sort(key=lambda x:x[0])
for i in ans:
print("{} = {} x {}".format(i[0],i[1],i[2]))
八皇后问题是在棋 盘上放皇后,互相不攻击,求方案。变换一下棋子,还可以有八车问题,八马问题,八兵问题,八王问题,注意别念反。在这道题里,棋子换成车,同时棋盘也得 换,确切说,是进行一些改造。比如现在有一张n*n的棋盘,我们在一些格子上抠几个洞,这些洞自然不能放棋子了,会漏下去的。另外,一个车本来能攻击和它 的同行同列。现在,你想想,在攻击的过程中如果踩到一个洞,便会自取灭亡。故,车的攻击范围止于洞。
此题,给你棋盘的规模n,以及挖洞情况,求放k个车的方案数(k从0到最多可放车数)
思路:利用邻接矩阵的不同值代表不同状态,0表示阻挡,1表示空位,2表示受到其他皇后的影响而不能放置,其中2可以叠加到4,这样回溯直接减2就可以恢复原来的状态
n=eval(input())
G=[]
for _ in range(n):
G.append(list(map(eval,input().split())))
ans=[0 for _ in range(64)]
def dfs(i,j,num):
global n,ans,G
ans[num-1]+=1
G[i][j]=2
temp_i=n
temp_j=n
for ii in range(i+1,n):
if G[ii][j]==0:
temp_i=ii
break
G[ii][j]+=2
for jj in range(j+1,n):
if G[i][jj]==0:
temp_j=jj
break
G[i][jj]+=2
for ii in range(i,n):
for jj in range(n):
if ii==i and jj<=j:
continue
if G[ii][jj]==1:
dfs(ii,jj,num+1)
G[i][j]=1
for ii in range(i+1,temp_i):
G[ii][j]-=2
for jj in range(j+1,temp_j):
G[i][jj]-=2
return
for i in range(n):
for j in range(n):
if G[i][j]==1:
dfs(i,j,1)
for i in ans:
if i==0:
break
print(i)
小弱T在闲暇的时候会和室友打扑克,输的人就要负责洗牌。虽然小弱T不怎么会洗牌,但是他却总是输。
渐渐地小弱T发现了一个规律:只要自己洗牌,自己就一定会输。所以小弱T认为自己洗牌不够均匀,就独创了一种小弱洗牌法。
小弱洗牌法是这样做的:先用传统洗牌法将52张扑克牌(1到K各四张,除去大小王)打乱,放成一堆,然后每次从牌堆顶层拿一张牌。如果这张牌的大小是 P(1到K的大小分别为1到13),那么就把这张牌插入到当前手中第P张牌的后面。如果当前手中不足P张牌,那么就把这张牌放在最后。
现在给你一对已经被打乱的牌,请你用小弱洗牌法进行洗牌,然后输出最后生成的序列。
注意:小弱可能在第一次洗牌时弄丢了某些牌,这时请你输出一个-1来提醒他牌的数目不够。
思路:简单的模拟
pai=[]
while True:
try:
nums=list(input().split())
pai.append(nums)
except:
break
dui=[]
for i in range(len(pai)):
for j in range(len(pai[i])):
dui.append(pai[i][j])
if len(dui)<52:
print(-1)
else:
dic_num=dict()
dic_num['1']=1
dic_num['2']=2
dic_num['3'] = 3
dic_num['4'] = 4
dic_num['5'] = 5
dic_num['6'] = 6
dic_num['7'] = 7
dic_num['8'] = 8
dic_num['9'] = 9
dic_num['10'] = 10
dic_num['J'] = 11
dic_num['Q'] = 12
dic_num['K'] = 13
ans=[]
for i in dui:
if dic_num[i]>len(ans):
ans.append(i)
else:
ans.insert(dic_num[i],i)
for i in ans:
print(i,end=' ')
print()
现代诗如蚯蚓
断成好几截都不会死
字符串断成好几截
有可能完全一样
请编写程序
输入字符串
输出该字符串最多能断成多少截完全一样的子串
样例说明
最多能断成四个”abc”,也就是abc重复四遍便是原串
同时也能断成两个”abcabc”
最坏情况是断成一个原串”abcabcabcabc”
思路:直接从头开始遍历,求最小的长度
n=input()
num=len(n)
flag=True
for i in range(1,num//2+1):
if n[:i]*(num//i) == n:
print(num//i)
flag=False
break
if flag:
print(1)
A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门 得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树就可以得到这Ai的美观度。但由于A城市土壤 肥力欠佳,两棵树决不能种在相邻的位置(i号位置和i+1号位置叫相邻位置。值得注意的是1号和n号也算相邻位置!)。
最终市政府给园林部门提供了m棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将m棵树苗全部种上,给出无解信息。
思路:注意是环形的,利用flag记录第一个节点是否种树
n,m=map(eval,input().split())
nums=list(map(eval,input().split()))
ans=-float('inf')
def dfs(i,temp_ans,temp_m,flag):
global n,m,ans,nums
temp_ans+=nums[i]
if temp_m==m:
if temp_ans>ans:
ans=temp_ans
else:
if i+2
有n个点和m个区间,点和区间的端点全部是整数,对于点a和区间[b,c],若a> =b且a< =c,称点a满足区间[b,c]。
求最小的点的子集,使得所有区间都被满足。
n, m = map(eval, input().split())
A = []
for i in range(n):
A.append(eval(input()))
A.sort() # A点集排序
B = []
for i in range(m):
B.append(list(map(int, input().split())))
B = sorted(B, key=lambda x: (x[0], -x[1])) # B区间排序
start = 0 # 定位推进区间
ans = 0
while start < m:
max_num = 0
max_index = 0
for i in range(len(A)): # 寻找使得start最接近m的点
temp = start
while temp < m:
if B[temp][0] <= A[i] <= B[temp][1]:
temp = temp + 1
else:
break
if temp > max_num: # 记录该点的下标和区间
max_num = temp
max_index = i
start = max_num # 更新start
del (A[max_index]) # 删除该点
ans = ans + 1
if len(A) == 0:
break
if start == m:
print(ans)
else:
print(-1)
大家都知道" 超级玛丽" 是一个很善于跳跃的探险家,他的拿手好戏是跳跃,但它一次只能向前跳一步或两步。有一次,他要经过一条长为n的羊肠小道,小道中有m个陷阱,这些陷阱都位于整数位置,分别是a1,a2,....am,陷入其中则必死无疑。显然,如果有两个挨着的陷阱,则玛丽是无论如何也跳过不去的。
现在给出小道的长度n,陷阱的个数及位置。求出玛丽从位置1开始,有多少种跳跃方法能到达胜利的彼岸(到达位置n)。
思路:类似于爬楼梯
n,m=map(eval,input().split())
trap=set(map(eval,input().split()))
dp=[1 for i in range(n)]
for i in range(m):
j=trap.pop()
if j<=n:
dp[j-1]=0
for i in range(2,n):
if dp[i]==0:
continue
else:
dp[i]=dp[i-1]+dp[i-2]
print(dp[n-1])
在上一季里,曾提到过质数的孤独,其实从另一个角度看,无情隔膜它们的合数全是质数的后代,因为合数可以由质数相乘结合而得。
如果一个合数由两个质数相乘而得,那么我们就叫它是质数们的直接后代。现在,给你一系列自然数,判断它们是否是质数的直接后代。
思路:根据数据范围先求出所有的质数,再逐个判断
T=eval(input())
def is_prime(num):
if num==2:
return True
else:
for i in range(2,int(num**0.5)+1):
if num%i==0:
return False
return True
prime_list=[]
for i in range(2,100000):
if is_prime(i):
prime_list.append(i)
def is_son(num):
global prime_list
if num%2==0:
if is_prime(num//2):
return True
return False
elif num==1:
return False
else:
for i in prime_list:
if i>num:
break
elif num%i==0 and num//i in prime_list:
return True
return False
for _ in range(T):
if is_son(eval(input())):
print("Yes")
else:
print("No")
为了准备一个学生节,组织者在会场的一片矩形区域(可看做是平面直角坐标
系的第一象限)铺上一些矩形地毯。一共有n 张地毯,编号从1 到n。现在将这些地毯按照
编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。
地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形
地毯边界和四个顶点上的点也算被地毯覆盖。
num=eval(input())
capmap=[]
for _ in range(num):
capmap.append(list(map(eval,input().split())))
loc=list(map(eval,input().split()))
flag=False
for i in range(num-1,-1,-1):
if capmap[i][0]<=loc[0] and capmap[i][0]+capmap[i][2]>=loc[0]:
if capmap[i][1]<=loc[1] and capmap[i][1]+capmap[i][3]>=loc[1]:
print(i+1)
flag=True
break
if not flag:
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。
思路:从两边直接判断
string=input().strip()
ans=0
for i in range(len(string)):
temp=0
temp_i=0
j=i
while True:
if string[j]=='b':
if temp_i==0:
temp_i=1
elif temp_i==2:
break
elif string[j]=='r':
if temp_i==0:
temp_i=2
elif temp_i==1:
break
temp+=1
j=(j+1)%len(string)
j=(i-1)%len(string)
temp_i=0
while True:
if string[j]=='b':
if temp_i==0:
temp_i=1
elif temp_i==2:
break
elif string[j]=='r':
if temp_i==0:
temp_i=2
elif temp_i==1:
break
temp+=1
j=(j-1)%len(string)
if temp>ans:
ans=temp
ii=i
print(ans)
你获得了一个据说是古代玛雅人制作的箱子。你非常想打开箱子看看里面有什么东西,但是不幸的是,正如所有故事里一样,神秘的箱子出现的时候总是会挂着神秘的锁。
这个锁上面看起来有 N 个数字,它们排成一排,并且每个数字都在 0 到 2 之间。你发现你可以通过锁上的机关来交换相邻两个数字的顺序。比如,如果原来有 5 个数字 02120,在一次交换以后你就可以得到 20120,01220,02210 或者 02102。
根据你所搜集的情报,这个锁在上面存在某连续四个数字是“2012”的时候会自动打开。现在,你需要计算一下,你至少需要进行多少次交换操作才能打开这把锁?
对样例的解释
把前两个数字交换以后,锁上的数字是 20120,其中存在连续四个数字2, 0, 1, 2,因此锁会打开。
思路:简单的bfs
from collections import *
n=eval(input())
string=input()
q=deque()
q.append([string,0,-1])
if string.count('1')<1 or string.count('2')<2 or string.count('0')<1:
print(-1)
else:
num_dict=defaultdict(int)
while len(q):
temp_string, step, index = q.popleft()
if '2012' in temp_string:
print(step)
break
for i in range(n - 1):
if i == index:
continue
else:
my_temp_string = temp_string[:i] + temp_string[i + 1] + temp_string[i] + temp_string[i + 2:]
if num_dict[my_temp_string]==0:
num_dict[my_temp_string]=1
q.append([my_temp_string, step + 1, i])