题干
AC code
n,k=map(int,input().split())
data=[]
for i in range(n):h,w=map(int,input().split())mid=[]mid.append(h)mid.append(w)data.append(mid)
front,tail=1,100000
def find(edge_len):global kans=0for wid,hei in data:ans+=(wid//edge_len)*(hei//edge_len)if ans>=k:return Truereturn False
while front<=tail:mid=(front+tail)//2if not find(mid):tail=mid-1else:front=mid+1
print(tail)
相关知识
对于list of list这类二维列表,可以有这种使用方式指代列表中的数据。
for a,b in 列表:
n,k=map(int,input().split())
data=[]
for i in range(n):h,w=map(int,input().split())mid=[]mid.append(h)mid.append(w)data.append(mid)
def find(edge_len):global kans=0for wid,hei in data:ans+=(wid+hei)*edge_lenreturn ans
print(find(3))
print(find(2))
如上图所示,对应输出可知
(5+4)*3+(3+2)*3=27+15=42
(5+4)*2+(3+2)*2=18+10=28
对应可以证明该想法正确。
[[1,3],[6,5],[7,9]]对应可以使用a,b in list进行指代,表示对应list中的元素。
思路整理(逐行代码解释)
-
for wid,hei in data:
: 遍历data列表中的每个长方形的宽度和高度。 -
ans+=(wid//edge_len)*(hei//edge_len)
: 计算当前长方形可以切割出的正方形数量,并累加到ans中。 -
if ans>=k:
如果ans大于或等于k,表示当前边长edge_len满足要求,可以切割出至少k个正方形。 -
return True
: 返回True,表示当前边长edge_len符合条件。 -
return False
: 如果循环结束后还未找到符合条件的边长,返回False。 -
while front<=tail
: 进入二分查找循环,当最小可能边长小于等于最大可能边长时执行。 -
mid=(front+tail)//2
: 计算当前边长的中点。 -
if not find(mid)
:如果当前边长mid无法切割出至少k个正方形。 -
tail=mid-1
: 更新最大可能边长为mid-1。 -
else:
:如果当前边长mid可以切割出至少k个正方形。 -
front=mid+1
: 更新最小可能边长为mid+1。 -
print(tail)
: 输出最大符合条件的正方形边长。