自己出的一道题,结果T了,求救(违规紫杉)
  • 板块学术版
  • 楼主stripe_python
  • 当前回复1
  • 已保存回复1
  • 发布时间2023/8/11 16:32
  • 上次更新2023/11/3 04:27:17
查看原帖
自己出的一道题,结果T了,求救(违规紫杉)
928879
stripe_python楼主2023/8/11 16:32

U326067

std拿py写的(因为这是我以前的py项目,反正是spj),是高斯消元+状态压缩的题,结果T飞,本蒟蒻又不会改c++,求大佬指导QwQ

py版std:

from math import ceil
from typing import List, Tuple

# 定义各种类型标

SolveType = List[Tuple[int, int]]
BoardType = List[List[int]]
EquationType = List[Tuple[List[Tuple[int, int]], Tuple[int, int]]]

WIDTH = 8   # 格数
WHITE, BLACK = 0, 1

def get_blank_board():  # 获取一个空白盘面
    return [[WHITE] * WIDTH for _ in range(WIDTH)]

def get_periphery(x: int, y: int):  # 求所有周边点,包括自己
    res = [(x, y)]
    for tx, ty in ((0, 1), (1, 0), (0, -1), (-1, 0)):
        nx, ny = x + tx, y + ty
        if 0 <= nx < WIDTH and 0 <= ny < WIDTH:
            res.append((nx, ny))
    return res

def equation():  # 列异或方程组
    res = []
    for x in range(WIDTH):
        for y in range(WIDTH):
            periphery = get_periphery(x, y)
            res.append((periphery, (x, y)))
    return res

def chunk(x: list, step: int):  # 按步长切割列表x
    step = int(step)
    return list(
        map(
            lambda n: x[n * step: n * step + step],
            list(range(0, ceil(len(x) / step)))
        )
    )

def gaussian(equ: EquationType):  # 异或方程组转矩阵
    matrix = []  # 增广矩阵
    # 系数1 系数2 ... 系数64 等号右侧
    for xs, pos in equ:
        p = []
        for x, y in xs:
            p.append(x * WIDTH + y)
        a = [0] * (WIDTH * WIDTH)
        for i in p:
            a[i] = 1  # 系数只有1或0
        a.append(array_to_int([pos]))  # 右端常数
        matrix.append(a)
    return matrix

def array_to_int(array: SolveType):  # 解法转十进制整数
    board = get_blank_board()
    for x, y in array:
        board[x][y] = BLACK
    flatten = lambda x: [y for L in x for y in flatten(L)] if type(x) is list else [x]   # 碾平二维列表
    a = flatten(board)
    del flatten
    res = [0] * (WIDTH * WIDTH)
    for inx, item in enumerate(a):
        if item == BLACK:
            res[inx] = 1
    res = ''.join(str(i) for i in res)   # 矩阵转二进制
    return int(res, base=2)   # 二进制转整数

def int_to_array(n: int):   # 十进制整数转解法
    lst = list(bin(n).replace('0b', ''))
    lst = ['0'] * (WIDTH * WIDTH - len(lst)) + lst   # 补0
    board = [0] * (WIDTH * WIDTH)
    for inx, item in enumerate(lst):
        if item == '1':
            board[inx] = BLACK
    board = chunk(board, WIDTH)
    return board

def guass(n: int, matrix: BoardType):  # 高斯消元法解异或方程组
    r = 0
    for c in range(n):
        t = r
        for i in range(r, n):  # 找1
            if matrix[i][c] == 1:
                t = i
                break

        if matrix[t][c] == 0:
            continue
        matrix[r], matrix[t] = matrix[t], matrix[r]  # 交换两行

        for i in range(r + 1, n):  # 1与r行异或
            if matrix[i][c] == 1:
                for j in range(c, n + 1):
                    matrix[i][j] ^= matrix[r][j]  # 合并

        r += 1

    for i in range(n - 1, -1, -1):  # 注意是倒序
        for j in range(i):
            if matrix[j][i] == 1:
                matrix[j][n] ^= matrix[i][n]

    for i in range(n):
        yield matrix[i][n]

def solve():  # 获取解方程的结果
    m = gaussian(equation())
    res = {}  # 哈希表存储
    for inx, num in enumerate(guass(WIDTH * WIDTH, m)):
        val = int_to_array(num)
        x, y = inx // WIDTH, inx % WIDTH  # 一维转二维公式
        res[(x, y)] = val
    return res

def merge(a: BoardType, b: BoardType):  # 合并两组解,实际上就是异或
    if not a:
        return b
    if not b:
        return a
    res = get_blank_board()
    for x, i in enumerate(a):
        for y, j in enumerate(i):
            k = b[x][y]
            if k == j:  # 异或核心
                res[x][y] = WHITE
            else:
                res[x][y] = BLACK
    return res

def get(board: BoardType):  # 主函数
    solution = solve()
    res = []
    for x, i in enumerate(board):
        for y, j in enumerate(i):
            if j == BLACK:
                res.append(solution[(x, y)])
    ans = []
    for i in res:
        ans = merge(ans, i)  # 合并解法,减少空间和可视化消耗

    res = []
    for x, i in enumerate(ans):
        for y, j in enumerate(i):
            if ans[x][y] == BLACK:
                res.append((x, y))
    return res

n = WIDTH = int(input())
a = get_blank_board()
for i in range(n):
    a[i] = list(map(int, input().split()))
res = get(a)
print(len(res))
for x, y in res:
    print(x + 1, y + 1)
2023/8/11 16:32
加载中...