概念
将问题的所有可能成为答案的解一一列举,然后根据问题所给出的条件判断此解是否合适,如果合适就保留,反之则舍弃。
42 点问题
题目描述:
众所周知在扑克牌中,有一个老掉牙的游戏叫做24点,选取4张牌进行加减乘除,看是否能得出24这个答案。
现在小蓝同学发明了一个新游戏,他从扑克牌中依次抽出6张牌,注意不是一次抽出,进行计算,看是否能够组成 42 点,满足输出YES,反之输出 NO。
最先抽出来的牌作为第一个操作数,抽出牌做第二个操作数,运算结果在当作第一个操作数,继续进行操作。
除不尽的情况保留整数。
请设计一个程序对该问题进行解答。
样例:
输入:
K A Q 6 2 3
输出:
YES
对于上面的样例我们进行了如下计算;
- KA=K 即 131=13
- 13/12=1 保留整数
- 1+6=7
- 7*2=14
- 14*3=42
运行限制:
最大运行时间:1s
最大运行内存: 128M
代码:
ans = [[] for i in range(10)]
a = ['0']*10
if __name__ == '__main__':
c = input().split()
for i in range(6):
if c[i] == 'A':
a[i] = 1
elif c[i] == 'J':
a[i] = 11
elif c[i] == 'Q':
a[i] = 12
elif c[i] == 'K':
a[i] = 13
else:
a[i] = ord(c[i]) - ord('0')
ans[0].append(a[0])
for i in range(1, 6):
for j in range(len(ans[i - 1])):
ans[i].append(ans[i - 1][j] + a[i])
ans[i].append(ans[i - 1][j] - a[i])
ans[i].append(ans[i - 1][j] * a[i])
ans[i].append(int(ans[i - 1][j] / a[i]))
flag = 0
for j in range(len(ans[5])):
if ans[5][j] == 42:
flag = 1
break
if flag == 1:
print("YES")
else:
print("NO")
# print(c)
# print(a)
# print(ans)
组合型枚举
排列组合相信大家都学习过,组合型枚举就是让你在 n 个中,随机选出 m 个,问你有多少种方案,而且每一种方案选择了哪 m 个,这就是组合型枚举。
即组合型枚举就是寻找Cm n的问题。
代码:
chosen = []
n = 0
m = 0
def calc(x):
if len(chosen) > m:
return
if len(chosen) + n - x + 1 < m:
return
if x == n + 1:
for i in chosen:
print(i,end=' ')
print('')
return
calc(x + 1)
chosen.append(x)
calc(x + 1)
chosen.pop()
if __name__ == '__main__':
tem = input().split()
n = int(tem[0])
m = int(tem[1])
calc(1)
公平抽签
题目描述:
小A的学校,蓝桥杯的参赛名额非常有限,只有m个名额,但是共有n个人报名,其中m<=n。作为老师非常苦恼,他不知道该让谁去,他在寻求一个绝对公平的方式。于是他准备让大家抽签决定,即m个签是去,剩下的是不去。
小A非常想弄明白最后的抽签结果是什么样子的,到底有多少种结果。
请设计一个程序帮助小A。最后输出各种情况的人名即可,一行一种情况,每种情况的名字按照报名即输入顺序排序。
第一行 输入 N M
第二行 到 第 N+1 行 共输入 N 个人名
每种情况输出 M 个人名,空格隔开。
样例:
输入:
3 2
xiaowang
xiaoA
xiaoli
copy
输出:
xiaowang xiaoA
xiaowang xiaoli
xiaoA xiaoli
运行限制:
- 最大运行时间:1s
- 最大运行内存:128M
题目解析:
实际上还是组合型枚举,但是输出元素为人名,我们可以将人名存起来,输出的时候,根据数字下标找到提前存好的人名,直接输出即可。
代码:
name = []
ans = []
chosen = []
n = 0
m = 0
def calc(x):
if len(chosen) > m:
return
if len(chosen) + n - x + 1 < m:
return
if x == n + 1:
ansTem = ""
for i in chosen:
ansTem = ansTem + name[i - 1] + ' '
# print(ansTem)
ans.append(ansTem)
return
calc(x + 1)
chosen.append(x)
calc(x + 1)
chosen.pop()
if __name__ == '__main__':
tem = input().split()
n = int(tem[0])
m = int(tem[1])
# print(n," ",m)
for i in range(n):
s = input()
name.append(s)
# print(name)
calc(1)
for i in range((len(ans) - 1), -1, -1):
print(ans[i])
排列型枚举
上面说过,组合型枚举就是让你在 n 个中,随机选出 m 个 ,问你有多少种方案,而且每一种方案选择了哪 m 个,这就是组合型枚举。
而排列型枚举相对组合型枚举就简单了一点,就是 n 个的全排列,即从 n 个中选取 n 个但是关心内部的顺序。
相比较组合只关心有多少个集合,而排列是关心集合内的排列方式。即排列型枚举就是寻找 Ann
代码:
order = [0] * 20
chosen = [0] * 20
n = 0
def calc(x):
if x == n + 1:
ansTem = ''
for i in range(1, n + 1):
print(order[i],end=' ')
print('')
return
for i in range(1,n+1):
if(chosen[i]==1) :
continue
order[x]=i
chosen[i]=1
calc(x+1)
chosen[i]=0
order[x]=0
if __name__ == '__main__':
n = int(input())
# print(name)
calc(1)
座次问题
题目描述:
小 A 的学校,老师好不容易解决了蓝桥杯的报名问题,现在老师又犯愁了。现在有 N 位同学参加比赛,但是老师想给他们排座位,但是排列方式太多了。老师非常想弄明白最后的排座次的结果是什么样子的,到底有多少种结果。
请设计一个程序帮助老师。
最后输出各种情况的人名即可,一行一种情况,每种情况的名字按照报名即输入顺序排序。
第一行 输入 N;
第二行 到 第N+1 行 共输入 N 个人名。
由于小 A 学校承办能力实在有限,所以其中 N 小于等于 10 人。
样例:
输入:
3
xiaowang
xiaoA
xiaoli
输出:
xiaowang xiaoA xiaoli
xiaowang xiaoli xiaoA
xiaoA xiaowang xiaoli
xiaoA xiaoli xiaowang
xiaoli xiaowang xiaoA
xiaoli xiaoA xiaowang
运行限制:
- 最大运行时间:1s
- 最大运行内存:128M
代码:
name = []
order = [0] * 20
chosen = [0] * 20
n = 0
def calc(x):
if x == n + 1:
ansTem = ''
for i in range(1, n + 1):
ansTem = ansTem + name[order[i]-1] + ' '
print(ansTem)
return
for i in range(1,n+1):
if(chosen[i]==1) :
continue
order[x]=i
chosen[i]=1
calc(x+1)
chosen[i]=0
order[x]=0
if __name__ == '__main__':
n = int(input())
for i in range(n):
s = input()
name.append(s)
# print(name)
calc(1)