我试图解决的问题是,想象一下每列中树的数量列表,例如: [10,20,10,0],此列表中的每个元素都是该列中存在的树的数量,表示在第一列中有十棵树,在第二列中有20棵树,依此类推。列数是固定的,通过剪切列,其数量将变为零。如果可能的话,你可以完全减少一行或一列,但是你只能在连续的行或列中减少,这意味着如果你有[4,0,4]则不能减少行以减少所有树木。 对于[4,0,4],只需要两次尝试,减少第一列和第三列。我会给你另一个例子,想象你有一个[4,3,4,3,4]列表,你可以减少三行并使其成为[1,0,1,0,1]但是你必须删除三列,总共需要6个步骤,但您也可以删除所有需要5个步骤的列,任何其他解决方案的结果都将大于5个步骤。
编辑:此图片将澄清问题: 首先,切割具有4个元素的列,然后切割第一行,然后切割现在有2个元素的列,然后切割最后一行或列。正如我之前所说,你不能削减具有不连续性的行。 (行中存在的所有元素应相邻,以便能够向下切割行)(在此图中,行#3具有不连续性) enter image description here
我正试图解决这个问题两天,我无处可去。我的最新代码在这里,在非正方形中进入几乎无限循环,例如[例如3个元素的列表,其中元素最多为200]树列表。
def cut_tree_row(tree):
res = []
discontinoue_flag = 0 # A flag to findout if cutting down the row is possible or not
non_zero_flag_once = 0 # if the program encounters a non_zero element for the first time this would change to 1
non_zero_flag_twice = 0# if the program encounters a non_zero element for the second time while the discontinue flag is 1, it would change to 1
for i in xrange(len(tree)):
if tree[i] > 0:
non_zero_flag_once = 1
if non_zero_flag_once == 1 and discontinoue_flag == 1:
non_zero_flag_twice = 1
else:
res.append(tree[i]-1)
else:
if discontinoue_flag == 0 and non_zero_flag_once == 1:
discontinoue_flag = 1
if discontinoue_flag == 1 and non_zero_flag_twice == 1:
return [], 10000000
res.append(0)
if discontinoue_flag == 1 and non_zero_flag_twice == 1:
return [], 10000000
return res , 1
def cut_tree_column(tree):
res = []
max_index = 0
m = max(tree)
flag = 1
if len(tree) == 0:
return tree , 0
for i in xrange(len(tree)):
if tree[i] == m and flag == 1:
flag = 0
res.append(0)
continue
res.append(tree[i])
return res , 1
def find_min_attempts(tree, total_sum = 0):
if len(tree) == 0:
return total_sum
s = sum(tree)
if s == 0:
return total_sum
res1 , num1 = cut_tree_column(tree)
res2 , num2 = cut_tree_row(tree)
return min(find_min_attempts(res1, total_sum + num1),find_min_attempts(res2, total_sum + num2))
def main():
tree = [187, 264, 298, 924, 319] #This input gives me an infinite loop
print find_min_attempts(tree)
main()
答案 0 :(得分:1)
此递归解决方案计算切割最大列之后的步数,以及最大行。它返回两者中的最小值。
如果存在零,则它将每个不连续部分解决为子问题。
def get_max_col(t):
""" Get index of tallest column """
return max(enumerate(t),key=lambda x: x[1])[0]
def remove_max_col(t):
""" Remove tallest column """
idx = get_max_col(t)
new_t = t[:]
new_t[idx] = 0
return new_t
def remove_bottom_row(t):
""" Remove bottom row """
return [x - 1 for x in t]
def splitz(iterable, val):
""" Split a list using val as the delimiter value """
result = []
group = []
for e in iterable:
if e == val:
if group: # ignore empty groups
result.append(group)
group = [] # start new
else:
group.append(e)
if group: # last group
result.append(group)
return result
def min_cuts(t):
# All zeroes, finished
if set(t) == set([0]):
return 0
# Single column
if len(t) == 1:
return 1
# All ones, single row
if set(t) == set([1]):
return 1
# If discontinued, add cost of subproblems
if 0 in t:
sub_ts = splitz(t, 0)
return sum(map(min_cuts, sub_ts))
# try removing the largest column and largest row(bottom)
# Pick the cheapest one
else:
t1 = remove_max_col(t)
x = 1 + min_cuts(t1)
t2 = remove_bottom_row(t)
y = 1 + min_cuts(t2)
return min(x, y)
print(min_cuts([4,3,4,3,4]))
print(min_cuts([187, 264, 298, 924, 319]))