解题思路:题目希望知道所有动作完成之后,哪些骨牌可以保持竖立。遍历骨牌数组来看,首先只需关注以'.'表示的、即初始时保持竖立的骨牌,然后根据这些'.'左右两边一定骨牌的受力来判断此骨牌是否最终竖立。首先大体分成三种情况。
- 若'.'在一行骨牌的开头,需保证它之后的最近的骨牌不会往左倒,即当它之后的骨牌均为'.',或往后第一个不为'.'的骨牌为‘R'时可保持竖立
- 若'.'在一行骨牌的末尾,需保证它之前的最近的骨牌不会往右倒,即当之前骨牌均为'.',或往前第一个不为'.'的骨牌为‘L'时可保持竖立
- 若'.'在中间,又可进一步分为几种不同情况,具体如下:
- L.L
- L..
- L.R
- ..L
- ...
- ..R
- R.L
- R..
- R.R;
其中第一、四,以及最后两种情况一定无法保持竖立;第三种情况由于左边骨牌向右倒,右边骨牌向左倒,第七种情况则是两边骨牌一起倒向中间,所以一定可以保持竖立。
对于第二种情况来说,当它之后的骨牌不向左倒即可保持竖立,即当它之后的骨牌均为'.',或往后第一个不为'.'的骨牌为‘R'时可保持竖立,类似1.中情况
对于第六种情况来说,当它之前的骨牌不向右倒即可保持竖立,即当之前骨牌均为'.',或往前第一个不为'.'的骨牌为‘L'时可保持竖立,类似2.中情况
而对剩余的第五情况来说,需要看此'.'骨牌两边的前缀和后缀,看两边离它最近的不为'.'的是什么骨牌,以此来决定向哪边倒,或保持竖立,具体代码如下所示。
result=[]
for i in range(num):
if data[i]!=".":
continue
# .R/.L
if i == 0:
x = data.find("L")
y = data.find("R")
if (y!=-1 and y < x) or x == y:
result.append(i+1)
# R./L.
elif i == num-1:
x = data[::-1].find("L")
y = data[::-1].find("R")
if (x != -1 and x < y) or x == y:
result.append(i + 1)
else:
# L.R
if data[i-1]=="L" and data[i+1]=="R":
result.append(i+1)
# L..
elif data[i-1]=="L" and data[i+1]==".":
x = data[i+1:].find("L")
y = data[i+1:].find("R")
# L..R
if (x > y and y!=-1) or x == y or (x ==-1 and y!= -1):
result.append(i + 1)
# ..R
elif data[i-1]=="." and data[i+1]=="R":
x = data[0:i][::-1].find("L")
y = data[0:i][::-1].find("R")
# L..R
if (x < y and (x !=-1)) or x == y or (y ==-1 and x!= -1):
result.append(i + 1)
# ...
elif (data[i - 1] == "." and data[i + 1] == "."):
str1 = data[:i-1][::-1] # 前缀
str2 = data[i+2:] # 后缀
x, y = -1, -1
for a in range(len(str1)):
if str1[a] != ".":
x = a
break
for b in range(len(str2)):
if str2[b] != ".":
y = b
break
if x==-1 and (y==-1 or str2[y]=="R"):
result.append(i + 1)
elif y==-1 and (x==-1 or str1[x]=="L"):
result.append(i + 1)
elif x!=-1 and y != -1:
if (x == y and str1[x] == "R" and str2[y] == "L") or (str1[x] == "L" and str2[y] == "R"):
result.append(i + 1)
# R.L
elif (data[i-1]=="R" and data[i+1]=="L"):
result.append(i + 1)
另外,还可以考虑骨牌的倒向与两边的左右倒的骨牌的数量有关。比如若骨牌'.'左边向右倒的骨牌数量大于其右边向左倒的骨牌数量,那么此骨牌同样不会竖立,而是会向右倒。对于此种题设,...和R.L属于同类情况,一起判断。下面是额外的代码:
# 若要看.两边R/L个数来决定
# ... / R.L
elif (data[i - 1] == "." and data[i + 1] == ".") or (data[i-1]=="R" and data[i+1]=="L"):
nR = 0 # 前缀倒序字符串中最后一个R的位置
nL = 0 # 后缀字符串中最后一个L的位置
for j in range(len(str1)):
if str1[j] == "L":
break
elif str1[j] == "R":
nR = j + 1 # 更新个数
for j in range(len(str2)):
if str2[j] == "R":
break
elif str2[j] == "L":
nL = j + 1 # 更新个数
# print(nR,nL)
if nR == nL:
result.append(i + 1)