📜  谜题 29 | (车轮拼图)(1)

📅  最后修改于: 2023-12-03 15:28:12.056000             🧑  作者: Mango

谜题 29 | (车轮拼图)

难度: 中等

题目描述

有一个车轮拼图,上面画有无限多条垂直平分线。给定一个已知的车轮拼图,你的任务是找到它的恰当分割和重新排列,使得所有平分线的位置都一样。

输入格式

输入是一个带有 $n$ 个位置的字符串,字符串中只包括数字 010 表示空格,1 表示有轮子。

例如,输入字符串 001001101 表示这张车轮拼图:

|  |  | |
1  00 1 1
|  |  | |

拼图中一共有四个轮子,分别在第 $1$、$3$、$4$、$8$ 个位置上。此外,拼图一共有 $5$ 条垂直平分线。

输出格式

输出是一行,为恰当的分割和重新排列后的车轮拼图,用同样的格式表示。如果有多个解,则输出其中的任意一个。

示例

输入:

01010

输出:

| |
1 1 1
| |

输入:

101101

输出:

|   |
0 1 1
|   |
1 0 1
|   |
提示

轮子的数量可能为奇数或偶数。拼图中的轮子的位置不需要连续。

解题思路

该题目可通过拼图中所有轮子在平分线左边、平分线上、平分线右边三种情况的组合情况来进行遍历。

经过遍历后得到所有组合情况,寻找判断可解的组合并输出。

此外,该题目可通过代码的细节解决模拟中的其他问题。

代码示例
def divide_and_conquer(middle_num, nums, pic):
    if len(nums) == 0:
        return pic, True

    divided_pic = [[] for _ in range(len(pic))]

    if middle_num not in nums:
        return [], False

    k = nums.index(middle_num)
    nums[k:k+1] = []
    
    for i in range(len(pic)):
        left_half = pic[i][:middle_num]
        right_half = pic[i][middle_num+1:] if middle_num+1 < len(pic[i]) else []
        
        if pic[i][middle_num] == " ":
            divided_pic[i].append(left_half)
            divided_pic[i].append(right_half)
            continue
        
        divided_pic[i].append(left_half + " ")
        divided_pic[i].append(" " + right_half)
        
    result, solved = divide_and_conquer(middle_num, nums[:], divided_pic)

    if solved:
        return result, solved

    for i in range(len(divided_pic)):
        if len(divided_pic[i][0]) != 0:
            edge_num = len(divided_pic[i][0])-1

            new_pic = []
            for l, r in zip(divided_pic, pic):
                l_edge = l[i][-1] if l[i][-1] != " " else r[edge_num]
                r_edge = r[i][0] if r[i][0] != " " else l[edge_num]
                new_pic.append(l[i] + r[i][1:])
                
            result, solved = divide_and_conquer(edge_num, nums[:], new_pic)

            if solved:
                return result, solved

    return [], False


def solve(strs):
    n = len(strs)

    nums_half = []
    nums_full = []
    pic = []

    h_flag = 0
    s_flag = 0
    h_pos = []
    for i in range(n):
        if strs[i] == "1":
            s_flag = 1
            nums_full.append(i)
            if h_flag:
                nums_half.append((h_pos[-1], i))
                h_flag = 0
            else:
                h_flag = 1
                h_pos.append(i)
        if strs[i] == "0":
            if s_flag == 1 and h_flag == 1:
                h_flag = 0

    wheel_num_full = len(nums_full)
    wheel_num_half = len(nums_half)

    for i in range(wheel_num_full):
        p = [" " if j != nums_full[i] else "1" for j in range(n)]
        pic.append("".join(p))

    for i in range(wheel_num_half):
        l, r = nums_half[i]
        p = [" " if j != l and j != r else "1" for j in range(n)]
        pic.append("".join(p))

    for i in range(n):
        if i == 0 or i == n-1 or strs[i] == "0":
            continue

        result, solved = divide_and_conquer(i, nums_full[:], pic)

        if solved:
            result.append("".join(["-" if j == " " else "|" for j in strs]))
            return "\n".join(result)

    return ""