**有这么一个“抽签”问题**
你的朋友提议一起玩个游戏,将写有数字的N个纸片放入口袋中,你可以从口袋中抽取四次纸片,每次记下纸片上数字后都将其再放回口袋。如果这4个数字的和是M,就算你赢了,否则就是你的朋友赢了。你挑战了好几次,结果一次都没有赢过,于是怒而撕破口袋,取出所有纸片,检查自己是否真的有赢的可能。请编写一个程序解决这个问题,如果存在则输出Yes,否则输出No.
限制条件
1 <= n <= 50
1 <= m <= 10**8
1 <= k <= 10**8
输入
n = 3
m = 10
k = {1,3,5}
输出
yes因为例如抽取四次1、1、3、5和就是10
输入
n = 3
m = 9
k = {1,3,5}
输出
no(不存在和为9的抽取方案)
n = input()
m = input()
k = input()
def solve():
flag = False
for a in range(n):
for b in range(n):
for c in range(n):
for d in range(n):
if k[a] + k[b] + k[c] + k[d] == m:
flag = True
if flag:
print("Yes")
else:
print("No")
solve()
我们考虑到上次如果n这个值无限增大,那么就很容易出现NP完全问题了。为了避免NP=P?出现,我们必须要优化自己的算法。
思路我们可以用二分搜索减少检索次数。
要记住所要查找的值m-ka-kb-kc为x,预先吧数组排序好,然后看K中间的数就可以了。可知
如果它比x小,x只能在它的后半段
如果它比x大,x只能在它的前半段
排序O(nlogn)时间
循环O(n3logn)时间
n3logn比logn大,我们这里合起来算O(n3longn)时间,于是,我们得到了抽签问题的在O(n3logn)时间内解决问题的算法。
n = input()
m = input()
k = input()
def binarySearch(x):
left = 0
right = len(k)-1
while right - left >= 1:
mid = (left + right) // 2
if k[mid] == x:
return True
elif k[left] > x:
left = mid + 1
else:
right = mid
return False
def solve():
sorted(k)
flag = False
for a in range(n):
for b in range(n):
for c in range(n):
if binarySearch(m - k[a] - k[b] - k[c]):
flag = True
if flag:
print("Yes ")
else:
print("No")
solve()
那么我们可以优化到O(n**3logn)是不是这个工程问题的最优解呢,答案不是,我们仍然有更快速的解决方案。
假设我们有四个数,我们可以分成两两考虑的想象力,这也叫分而治之,在大禹治水时期,古人就能想到这个高明的方法来治水,我们今天可以拿来优化我们的算法。此外,像这样从复杂度较高的算法出发,不断降低复杂度知道满足问题要求的过程,也是设计算法必须经历的一个过程。
我们用分而治之这种思想来优化我们的算法
检查是否有c和d使得kc + kd = m-ka-kb
这种情况并不能直接使用二分搜索。但是,如果预先枚举出kc+kd所得n2个数字并排好序,便可利用二分搜索了。
该算法
排序O(n2logn)时间
循环O(n2logn)时间
总的也是O(n2logn)时间,这样可以确信即便n=1000000也能妥善应对了。
n = input()
m = input()
k = input()
def binarySearch(x):
left = 0
right = len(k)-1
while right - left >= 1:
mid = (left + right) // 2
if k[mid] == x:
return True
elif k[left] > x:
left = mid + 1
else:
right = mid
return False
# 创建一个新列表,用来存放c和d的和。
kk = [0]*n*n
def solve():
flag = False
for c in range(n):
for d in range(n):
kk[c*n+d] = k[c] + k[d]
sorted(kk)
for a in range(n):
for b in range(n):
if binarySearch(m - k[a] - k[b]):
flag = True
if flag:
print("Yes")
else:
print("No")
solve()