一、题目
题目 2302: 蓝桥杯2019年第十届省赛真题-糖果 时间限制: 1Sec 内存限制: 128MB 提交: 1502 解决: 432 题目描述 糖果店的老板一共有 M 种口味的糖果出售。为了方便描述,我们将 M 种 口味编号 1 ~ M。
小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而 是 K 颗一包整包出售。
幸好糖果包装上注明了其中 K 颗糖果的口味,所以小明可以在买之前就知 道每包内的糖果口味。
给定 N 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖 果。
输入 第一行包含三个整数 N、M 和 K。
接下来 N 行每行 K 这整数 T1, T2, · · · , TK,代表一包糖果的口味
(对于 30% 的评测用例,1 ≤ N ≤ 20 。
对于所有评测样例,1 ≤ N ≤ 100,1 ≤ M ≤ 20,1 ≤ K ≤ 20,1 ≤ Ti ≤ M 。)
输出 一个整数表示答案。如果小明无法品尝所有口味,输出 ?1。
样例输入
6 5 3
1 1 2
1 2 3
1 1 3
2 3 5
5 4 2
5 1 2
样例输出
2
二、思路和代码
dfs用的搜索,状态压缩和动态规划参考大佬cpp题解但最终甚至分数更低。虽然如此,状态压缩还是学到了。
2.1 bfs+小根堆+状态压缩(60)
import heapq
N, M, K = [int(x) for x in input().split()]
ls = list()
ls.append([])
for _ in range(N):
ls.append([int(x) for x in input().split()])
queue = list()
def getState(pack):
res = 0
for x in pack:
res = res | 1 << (x - 1)
return res
for i in range(1, N + 1):
ls[i] = getState(ls[i])
class Node:
def __init__(self, x, y, z):
self.data = [x, y, z]
def __gt__(self, other):
return self.data[2] > other.data[2]
def __ge__(self, other):
return self.data[2] >= other.data[2]
def __lt__(self, other):
return self.data[2] < other.data[2]
def __le__(self, other):
return self.data[2] <= other.data[2]
heapq.heappush(queue, Node(0, 1, 0))
destination = pow(2, M) - 1
res = 0
while len(queue) != 0:
cur = heapq.heappop(queue)
data = cur.data
if data[1] == N + 1:
continue
data1 = data[0] | ls[data[1]]
if data1 == destination:
res = data[2]
break
tempnode = Node(data1, data[1] + 1, data[2] + 1)
heapq.heappush(queue, tempnode)
tempnode = Node(data[0], data[1] + 1, data[2])
heapq.heappush(queue, tempnode)
if len(queue) == 0:
print(-1)
else:
print(res)
2.2dfs(40)
dfs(40分):
N, M, K = [int(x) for x in input().split()]
ls = list()
ls.append([])
for _ in range(N):
ls.append([int(x) for x in input().split()])
havntused = [i for i in range(N+1)]
tasted = [0 for _ in range(M+1)]
res = float("inf")
def dfs(packs):
global res, tasted
if packs >= res:
return
if sum(tasted) == M:
res = min(res, packs)
return
if len(havntused) == 1:
return
for i in range(1, len(havntused)):
tasted0 = tasted[:]
pack = havntused.pop(i)
for x in ls[pack]:
tasted[x] = 1
dfs(packs+1)
havntused.insert(i, pack)
tasted = tasted0
dfs(0)
if res == float("inf"):
print(-1)
else:
print(res)
2.3状态压缩和dp(10分)
N, M, K = [int(x) for x in input().split()]
ls = list()
for _ in range(N):
ls.append([int(x) for x in input().split()])
def getState(pack):
res = 0
for x in pack:
res = res | 1<<(x-1)
return res
dp = [float("inf") for _ in range(pow(2, M))]
for i in range(N):
state = getState(ls[i])
ls[i] = state
dp[state] = 1
for k in range(N):
for j in range(pow(2, M)):
if dp[j] != float("inf"):
dp[j|ls[k]] = min(dp[j]+1, dp[j|ls[k]])
if dp[pow(2, M)-1] == float("inf"):
print(-1)
else:
print(dp[pow(2, M)-1])
|