这不是我正在努力做的作业,但我正在尝试解决问题(如果有兴趣https://open.kattis.com/problems/azulejos,请点击此处。)
实际上,您不必了解这个问题,但是我现在想完成的是,我只想从多个列表中选择一个元素,并且它们不会相互重叠。
例如,在代码末尾,我得到一个输出:
{1: [1, 2, 3], 2: [1, 2, 3, 4], 3: [2, 4], 4: [1, 2, 3, 4]}
例如,我想将其转换为
{3: 4, 2: 2, 4:1, 1: 3} -- which is the sample answer that is in the website.
但是据我了解,它也可以很简单
{1: 3, 2: 2, 3: 4, 4: 1}
我正在努力选择仅一个与其他整数不重叠的整数。我在代码中生成的字典包含具有多个整数的列表。我只想从中选择一个,而且它们都是独一无二的
import sys
n_tiles_row = int(sys.stdin.readline().rstrip())
# print(n_tiles_row) ==> 4
# BACK ROW - JOAO
back_row_price = sys.stdin.readline().rstrip()
# print(back_row_price) ==> 3 2 1 2
back_row_height = sys.stdin.readline().rstrip()
# print(back_row_height) ==> 2 3 4 3
# FRONT ROW - MARIA
front_row_price = sys.stdin.readline().rstrip()
# print(front_row_price) ==> 2 1 2 1
front_row_height = sys.stdin.readline().rstrip()
# print(front_row_height) ==> 2 2 1 3
br_num1_price, br_num2_price, br_num3_price, br_num4_price = map(int, back_row_price.split())
# br_num1_price = 3; br_num2_price = 2; br_num3_price = 1; br_num4_price = 2;
br_num1_height, br_num2_height, br_num3_height, br_num4_height = map(int, back_row_height.split())
# 2 3 4 3
fr_num1_price, fr_num2_price, fr_num3_price, fr_num4_price = map(int, front_row_price.split())
# 2 1 2 1
fr_num1_height, fr_num2_height, fr_num3_height, fr_num4_height = map(int, front_row_height.split())
# 2 2 1 3
back_row = {1: [br_num1_price, br_num1_height],
2: [br_num2_price, br_num2_height],
3: [br_num3_price, br_num3_height],
4: [br_num4_price, br_num4_height]}
# {1: [3, 2], 2: [2, 3], 3: [1, 4], 4: [2, 3]}
front_row = {1: [fr_num1_price, fr_num1_height],
2: [fr_num2_price, fr_num2_height],
3: [fr_num3_price, fr_num3_height],
4: [fr_num4_price, fr_num4_height]}
# {1: [2, 2], 2: [1, 2], 3: [2, 1], 4: [1, 3]}
_dict = {1: [],
2: [],
3: [],
4: []
}
for i in range(n_tiles_row):
_list = []
for n in range(n_tiles_row):
if(list(back_row.values())[i][0] >= list(front_row.values())[n][0]
and list(back_row.values())[i][1] >= list(front_row.values())[n][1]):
_list.append(list(front_row.keys())[n])
_dict[list(back_row.keys())[i]] = _list
print(_dict)
# {1: [1, 2, 3], 2: [1, 2, 3, 4], 3: [2, 4], 4: [1, 2, 3, 4]}
请告诉我是否有其他方法可以解决此问题。
答案 0 :(得分:0)
解决问题的一种可能无效的方法是生成所有可能的“解决方案”(其值可能在与特定键相对应的列表中不存在)并满足“有效”的要求(所有值都适用)出现在相应的列表中。
使用itertools.permutation
(能够计算出满足唯一性约束的所有可能解)的一种方法是:
import itertools
def gen_valid(source):
keys = source.keys()
possible_values = set(x for k, v in source.items() for x in v)
for values in itertools.permutations(possible_values):
result = {k: v for k, v in zip(keys, values)}
# : check that `result` is valid
if all(v in source[k] for k, v in result.items()):
yield result
d = {1: [1, 2, 3], 2: [1, 2, 3, 4], 3: [2, 4], 4: [1, 2, 3, 4]}
next(gen_valid(d))
# {1: 1, 2: 2, 3: 4, 4: 3}
list(gen_valid(d))
# [{1: 1, 2: 2, 3: 4, 4: 3},
# {1: 1, 2: 3, 3: 2, 4: 4},
# {1: 1, 2: 3, 3: 4, 4: 2},
# {1: 1, 2: 4, 3: 2, 4: 3},
# {1: 2, 2: 1, 3: 4, 4: 3},
# {1: 2, 2: 3, 3: 4, 4: 1},
# {1: 3, 2: 1, 3: 2, 4: 4},
# {1: 3, 2: 1, 3: 4, 4: 2},
# {1: 3, 2: 2, 3: 4, 4: 1},
# {1: 3, 2: 4, 3: 2, 4: 1}]
这将生成n!
个解决方案。
在列表上使用笛卡尔积的“强力”方法产生prod(n_k) = n_1 * n_1 * ... * n_k
个解决方案(每个列表的长度为n_k
)。在最坏的情况下(最大密度),这是n ** n
个解,在渐近性上比阶乘差。
在最佳情况下(最小密度),这仅是1个解决方案。
通常,这可能比上面建议的“置换解决方案”慢或快,具体取决于列表的“稀疏性”。
平均n_k
约。 n / 2
,n!
比n >= 6
小/快。
平均n_k
约。 n * (3 / 4)
,n!
比n >= 4
小/快。
在此示例中,有4! == 4 * 3 * 2 * 1 == 24
个置换解决方案和3 * 4 * 2 * 4 == 96
个笛卡尔乘积解决方案。
答案 1 :(得分:0)
这是使用与您提供的代码相同的语法的解决方案。
这里的技巧是先按价格升序(要求不降序)然后按高度降序排列磁贴,以使后排价格第二低的最高磁贴与该行中的最高磁贴匹配。前排的下一个最低价格。
为此,我利用了Python的sorted()
函数。请参阅堆栈溢出示例here。
我认为如果没有这样的匹配项,那么会根据您链接的问题立即中断并打印。
请注意,您最初声称是python字典
{3: 4, 2: 2, 4:1, 1: 3}
等同于{1: 3, 2: 2, 3: 4, 4: 1}
。没错,您必须记住,在Python字典中,对象默认情况下是未排序的,因此以这种方式比较键并不容易。
import sys
n_tiles_row = int(sys.stdin.readline().rstrip())
# print(n_tiles_row) ==> 4
# BACK ROW - JOAO
back_row_price = sys.stdin.readline().rstrip()
# print(back_row_price) ==> 3 2 1 2
back_row_height = sys.stdin.readline().rstrip()
# print(back_row_height) ==> 2 3 4 3
# FRONT ROW - MARIA
front_row_price = sys.stdin.readline().rstrip()
# print(front_row_price) ==> 2 1 2 1
front_row_height = sys.stdin.readline().rstrip()
# print(front_row_height) ==> 2 2 1 3
# preprocess data into lists of ints
back_row_price = [int(x) for x in back_row_price.strip().split(' ')]
back_row_height = [int(x) for x in back_row_height.strip().split(' ')]
front_row_price = [int(x) for x in front_row_price.strip().split(' ')]
front_row_height = [int(x) for x in front_row_height.strip().split(' ')]
# store each tile into lists of tuples
front = list()
back = list()
for i in range(n_tiles_row):
back.append((i, back_row_price[i], back_row_height[i])) # tuples of (tile_num, price, height)
front.append((i, front_row_price[i], front_row_height[i]))
# sort tiles by price first (as the price must be non-descending) then by height descending
back = sorted(back, key=lambda x: (x[1], -x[2]))
front = sorted(front, key=lambda x: (x[1], -x[2]))
# print(back) ==> [(2, 1, 4), (1, 2, 3), (3, 2, 3), (0, 3, 2)]
# print(front) ==> [(3, 1, 3), (1, 1, 2), (0, 2, 2), (2, 2, 1)]
possible_back_tile_order = list()
possible_front_tile_order = list()
for i in range(n_tiles_row):
if back[i][2] > front[i][2]: # if next lowest priced back tile is taller than next lowest priced front tile
possible_back_tile_order.append(back[i][0])
possible_front_tile_order.append(front[i][0])
else:
break
if len(possible_back_tile_order) < n_tiles_row: # check that all tiles had matching pairs in back and front
print("impossible")
else:
print(possible_back_tile_order)
print(possible_front_tile_order)