AcWing 116. 飞行员兄弟
原题链接
简单
作者:
Sondottt
,
2025-01-04 16:11:43
,
所有人可见
,
阅读 5
思路: 枚举每一种方案:也就是一个位置是否被操作。一个位置有两种方案,也就是被操作,不被操作,一共2的16次方种。可以用二进制的方式枚举,1表示被操作,0表示不被操作,因此将op从0到2的16次方-1进行枚举。
Q:怎么得到每个状态位?
A:使用移位运算
注意事项: Python中的拷贝问题:
1.赋值:两个引用指向同一个对象。
2.浅拷贝:copy 嵌套对象是共享的,是对引用进行拷贝。
3.深拷贝:deepcopy 两个对象完全独立,互不影响。
算法1
(暴力枚举)
Python 代码
import copy
def get(i, j):
return 4 * i + j
def all_open():
for i in range(4):
for j in range(4):
if st[i][j] == '+': # 判断是否存在 '+'
return False
return True
def turn_one(i, j):
if st[i][j] == '+':
st[i][j] = '-'
else:
st[i][j] = '+'
def turn_all(x, y):
for i in range(4):
turn_one(x, i) # 翻转行 x
turn_one(i, y) # 翻转列 y
turn_one(x, y) # 翻转 (x, y) 本身
if __name__ == '__main__':
st = []
res = []
for i in range(4):
s = list(input()) # 读取输入
st.append(s)
for op in range(1 << 16):
backup = copy.deepcopy(st) # 使用深拷贝
temp = []
for i in range(4):
for j in range(4):
if op >> get(i, j) & 1: # 判断当前位是否为 1
temp.append([i, j])
turn_all(i, j)
if all_open(): # 检查是否全部为 '-'
if len(temp) < len(res) or len(res) == 0:
res = temp.copy()
st = backup # 恢复原始状态
print(len(res)) # 输出结果的长度
for r in res: # 输出翻转操作的具体位置
print(r[0] + 1, r[1] + 1)