1.字符串匹配
现在给你一个只包含"()[]"括号的字符串,问你至少加多少个字符是合法的,对于字符串合法的定义为:
1.字符串为空是合法的
2.若字符串A合法,则字符串(A), [A]也是合法的
3.若字符串A和字符串B均合法,则AB合法
详情参考: 动态规划
输入: 第一行输入一个字符串s,保证只有题目要求的字符 1 <= len(s) <= 200
输出: 输出最少需要添加几个字符可以构成合法的字符串
思想:
这是一个区间动态规划问题:
状态定义:使用二维dp,dp[i][j]表示从s[i]到s[j]的最少添加括号个数
初始化:单独一个字符时,dp[i][j]=1,因为一个字符必定需要添加一个括号,其他值先赋值为0
状态转移方程:
循环遍历区间长度(区间长度m从1到n),每次考虑[i,j]内的区间(i从0开始,j=i+m),
如果s[i]和s[j]匹配,那么dp[i][j]=dp[i+1][j-1],也即括号里面部分需要添加的最少括号数.
如果s[i]和s[j]不能匹配,那么必定存在一个分界位第k位,使得从第i位到第k位所需要加的最少括号数量dp[i][k]和第k+1位到第j位所需要加的括号数量dp[k+1][j]相加起来的和能够凑成整个问题的最优值,即dp[i][j]=min(dp[i][j], dp[i][k] + dp[k+1][j])
def match(a, b):
# 判断是否匹配
if a == '[' and b == ']':
return True
if a == '(' and b == ')':
return True
return False
def kuohaomatch(s):
n = len(s)
dp = [[n] * n for _ in range(n)]#nxn大小的矩阵,因为求最小,初始n
#初始化,自己到自己最少添加1
for i in range(n):
dp[i][i] = 1
#依次遍历区间长度维1,2,3,...,n
for m in range(1, n + 1):
for i in range(n - m):
j = i + m
if match(s[i], s[j]):#能匹配的话
dp[i][j] = dp[i + 1][j - 1]
else:#不能匹配的话
for k in range(i, j):
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j])
return dp[0][n - 1]#返回从s[0]到s[n]的最少添加括号个数
s = '((]]()]'
print(kuohaomatch(s)) #结果:5
2.求面积
一个二次曲线 y = A x 2 + x + B , x = C , x = D y=Ax^2+x+B, x=C, x=D y=Ax2+x+B,x=C,x=D,与 x x x轴围城的面积。
思想:
当A=0时,围城的区域是梯形
当A1!=0时,围城的区域是曲面,利用积分的思想:以直代曲,无线分割,求和近似
因为考虑到精度问题,C-D区间分割100万份,再分成1000,取每份中间的矩形*500,但是还是没通过所有用例。
考试的时候竟然numpy不能用!!!!
"""
li=abs(d-c)/1000000
sum1=0
for i in range(0,1000000,1000):
a1=c+(i+500)*li
a2=c+(i+501)*li
sum2=500*abs(a2-a1)*(a2+a*a2*a2+a*a1*a1+a1+2*b)
sum1=sum1+sum2
return sum1
"""
import numpy as np
n=int(input())
def fun(a,b,c,d):
if c==d:
return 0
if not a:
return(0.5*abs(d-c)*(c+d+2*b))
if a!=0 and c!=d:
li=np.linspace(c,d,1000000)
sum1=0
for i in range(0,len(li),1000):
a1=li[i+500]
a2=li[i+501]
sum2=500*abs(a2-a1)*(a2+a*a2*a2+a*a1*a1+a1+2*b)
sum1=sum1+sum2
return sum1
ans=[]
for i in range(n):
a,b,c,d=map(int,input().strip().split())
s=fun(a,b,c,d)
ans.append(s)
for i in range(len(ans)):
print(ans[i],' ',)
if i ==len(ans):
print(ans[i])
3.排列组合题
从N个人当中选出M个人组队,在M个人当中选出一个人当队长,当选出的集合相同时而当队长的人不一样时,则为两个不同的方案,请用代码实现共有多少中组队方案?
思想:
C(n,m)*m
n,m=list(map(int,input().split()))
print(Cfun(n,m)*m)
组合C(n,m)函数的实现
def Cfun(n,m):
a=b=result=1
if n<m:
print("n不能小于m 且均为整数")
for j in range(0,m):
#使用变量a,b 让所用的分母相乘后除以所有的分子
a=a*(n-j)
b=b*(m-j)
result=a//b #在此使用“/”和“//”均可,因为a除以b为整数
return result
排列A(n,m)函数的实现
def Afun(n,m):
a=1
if n<m:
print("n不能小于m 且均为整数")
for j in range(0,m):
#使用变量a,b 让所用的分母相乘后除以所有的分子
a=a*(n-j)
return a
小Q有X首长度为A的不同的歌和Y首长度为B的不同的歌,现在小Q想用这些歌组成一个总长度正好为K的歌单,每首歌最多只能在歌单中出现一次,在不考虑歌单内歌曲的先后顺序的情况下,请问有多少种组成歌单的方法。
#接收输入
k = int(input())
a, x, b, y = list(map(int,input().split()))
#遍历
res = 0
# a*x+b*j=k有很多种情况,需要循环,确定从x中挑选出i首和y中选出j首,因为组合前后均不考虑顺序
for i in range(1,x+1):
for j in range(1,y+1):
if (i * a + j * b) == k:
res = res + Cfun(x,i)*Cfun(y,j)#调用上面的组合函数
#取模打印
if i <1000000007:
print(res)
else:
print(res%1000000007)
4.图
题目忘记了,打算做个专场
5.最短路径
题目忘记了,打算做个专场
6.画图
画家小Q又开始他的艺术创作。小Q拿出了一块有NxM像素格的画板, 画板初始状态是空白的,用’X’表示。
小Q有他独特的绘画技巧,每次小Q会选择一条斜线, 如果斜线的方向形如’/’,即斜率为1,小Q会选择这条斜线中的一段格子,都涂画为蓝色,用’B’表示;如果对角线的方向形如’’,即斜率为-1,小Q会选择这条斜线中的一段格子,都涂画为黄色,用’Y’表示。
如果一个格子既被蓝色涂画过又被黄色涂画过,那么这个格子就会变成绿色,用’G’表示。
小Q已经有想画出的作品的样子, 请你帮他计算一下他最少需要多少次操作完成这幅画。
每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数N和M(1 <= N, M <= 50), 表示画板的长宽。
接下来的N行包含N个长度为M的字符串, 其中包含字符'B','Y','G','X',分别表示蓝色,黄色,绿色,空白。整个表示小Q要完成的作品。
输出描述:
输出一个正整数, 表示小Q最少需要多少次操作完成绘画。
输入
4 4
YXXB
XYGX
XBYY
BXXY
输出
3
思想:
因为’Y’只会以斜率 -1 出现,'B’只会以斜率 1 出现,所以这道题就变得十分简单。直接逐行逐列遍历,对于第 i 行第 j 列的元素 T[i][j],分析一下它的几种可能性如下:
1、T[i][j] == ‘Y’,此时只需看看它的左上角元素是否也为 ‘Y’ or ‘G’ 即可,如果是,那么该元素可以被上面的元素以同一笔绘制而成,否则,需要新起一笔,cnt += 1;
2、T[i][j] == ‘B’,观察它的右上角元素是否也为 ‘B’ or ‘G’ 即可,如若不是,cnt += 1;
3、T[i][j] == ‘G’,把上面两步都过一遍即可。
最后的 cnt 记录的便是最少用的笔数。
N, M = map(int, input().strip().split())
T = []
for i in range(N):
T.append(input().strip())
cnt = 0
for i in range(N):
for j in range(M):
if T[i][j] == 'X': continue
if T[i][j] in ['Y', 'G']:
if i - 1 >= 0 and j - 1 >= 0 and T[i-1][j-1] in ['Y', 'G']: cnt += 0
else: cnt += 1
if T[i][j] in ['B', 'G']:
if i - 1 >= 0 and j + 1 < M and T[i-1][j+1] in ['B', 'G']: cnt += 0
else: cnt += 1
print(cnt)
7.最大公因数
**备注:不是特别懂这个题,欢迎大家评论。**
def gcd_2(a,b): #求两个数的最大公约数
"""
先用小的一个数除大的一个数,得第一个余数;
再用第一个余数除小的一个数,得第二个余数;
又用第二个余数除第一个余数,得第三个余数;
这样逐次用后一个数去除前一个余数,直到余数是0为止。
那么,最后一个除数就是所求的最大公约数(如果最后的除数是1,那么原来的两个数是互质数)。
"""
a,b = max(a,b),min(a,b)
if a%b == 0:
return b
else:
return gcd_2(b,a%b)
def gcd_many(s): #求全部的
g = s[0]
for i in range(1,len(s)):
#求数组的最大公约数转变为求两个数的最大公约数
g=gcd_2(g,s[i])
return g
if __name__ == '__main__':
data= list(map(int,input().split()))
#存放最大公因数数组,默认删除从0-n-1
ans=[]
for i in range(len(data)):
ans.append(gcd_many(data[i:]))
ans_sort=sorted(ans)
print('为最大公因数:')
print(ans_sort)
#存放删除的位置,调换位置
res=[]
for i in range(len(ans_sort)):
aa=ans.index(ans_sort[i])+1
if i>0 and aa in res :
res.append(res[-1]+1)
else:
res.append(aa)
print('为使最大公因数字典序最大,原来数组删除的顺序:')
print(res)
思路:
找出数组中每个重复元素的个数并减去1=执行的操作
data=[1, 1, 2, 3, 4, 5, 6 ,7, 8, 8, 8, 9, 9, 10, 11, 12, 12]
data_set=list(set(data))#去重后的数组
ret = []
for i in data_set:
data.remove(i)#对原数组都移除一个元素,剩下的都是有重复的元素
print(len(data))#5