运行要求
运行时间限制: 2sec
内存限制: 1024MB
原题链接
题目
刚刚开始代码竞技的小明同学有M个算法想要学习。最开始的时候,小明同学对每一个算法的理解度都是0。
小明去了书店,书店里在买N本参考书。第i本参考书(1<=i<=N)的售价为Ci元。买下第i本参考书的话,小明对于第j(1<=j<=M)个算法的理解度将会提升A(i,j)。
除此以外没有其他的方法能够帮助小明提升对于算法的理解。
小明同学的目标是要对M个算法的理解度提升到X以上。判断小明能不能通过购买参考书的方式达到目标,如果能够达到目标的话,求出达到目标所需要花的最少的买参考书的钱。
输入前提条件
- 所有的输入均为整数
- 1 <=N,M <= 12
- 1 <= X <= 10^5
- 1 <= Ci <= 10^5
- 0 <= A(i,j) <= 10^5
输入
N M X
C1 A(1,1) A(1,2) ⋯ A(1,M)
C2 A(2,1) A(2,2) ⋯ A(2,M)
⋮
CN A(N,1) A(N,2) ⋯ A(N,M)
输出
如果小明不能够通过购买参考书达到目标的话,输出-1
如果可以通过购买参考书达到目标的话,输出需要的最小的金额。
例1
输入
3 3 10
60 2 2 4
70 8 7 9
50 2 3 9
输出
120
买第2本和第3本参考书,总共话费120元,可以把所有的算法理解度提升到10以上。这是所需要花费的最少的金额。
例2
输入
3 3 10
100 3 1 4
100 1 5 9
100 2 6 5
输出
-1
就算买走所有的参考书,也无法将第1个算法的理解度提升至10以上。
例3
输入
8 5 22
100 3 7 5 3 1
164 4 5 2 7 8
334 7 2 7 2 9
234 4 7 2 8 2
541 5 4 3 3 6
235 4 8 6 9 7
394 3 6 1 6 2
872 8 4 3 7 2
输出
1067
读懂题目
可以把题目抽象成如下
题目给定义N,M,X和一个纬度为(N,M)的数组。从中跳出几行数组元素,能够能够满足挑选出来的几行数组的列方向的和要大于X
解题思路
咋一看是不是要用动态规划呀
再看一看条件1<=N<=12
最多有12本书,数有买和不买2种状态,所以书的状态最多要2^12=4096种状态
每本书有M个算法,1<=M<=12,也就是说每本书最多要遍历12个算法
总共要遍历4096*12 = 49152次
那么我们可以通过比特运算的方式对所有书的购买情况做一个遍历
然后筛选出满足条件的书的购买情况
最后再从满足条件的情况中选择花费最少的情况即可
代码
N, M, X = map(int, input().split())
ARR = []
for i in range(N):
ARR.append(list(map(int, input().split())))
def calculate(n, m, x, arr):
result = []
for i in range(2 ** n):
tmpValue = 0
mrr = [0] * m
krr = [False] * m
for j in range(n):
res = i >> j & 1
if res == 1:
tmpValue = tmpValue + arr[j][0]
for mIndex in range(m):
mrr[mIndex] = mrr[mIndex] + arr[j][mIndex + 1]
if mrr[mIndex] >= x:
krr[mIndex] = True
if sum(krr) == m:
result.append(tmpValue)
if len(result) == 0:
print(-1)
else:
print(min(result))
calculate(N, M, X, ARR)
总结
这道题考察了对比特运算的敏感度,通过对题目给出的条件的阅读,判断出遍历所有情况的可行性,从而选择用比特运算的方式取遍历所有的购买书的方案。
※ 另外,我会在我的微信个人订阅号上推出一些文章,欢迎关注
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。