我遇到一个问题,那就是您可以唤醒一个正在睡觉的人,这个人的状态从代表睡觉的S
变为代表醒来的.
。
当您唤醒一个人时,由于距离很近,旁边的人也会从睡眠中醒来。例如,有三个人在一个房间里睡觉。如果您在中间唤醒一个人,那么三个人都将醒来,即SSS
变成...
。
但是,如果您唤醒已经清醒的人,那么他的状态将不会改变。但是他旁边的人会醒着,即S.S
变成...
,
问题是给定一个房间s
,里面有熟睡的人S
和清醒的人.
。唤醒k
个人之后,该房间中最多可容纳多少人。
一个棘手的例子是s
= S.SSSS
和k
= 2
。
s[4]
,那么房间将是S.S...
s[1]
,那么房间将是......
也就是说,您可以在唤醒s[4]
人和s[1]
人之后使房间中的每个人都醒着。因此,此示例的答案将是6
个人,而不是5
。
我用python列出了所有可以唤醒的人的索引组合来编写我的解决方案。唤醒他们并计算清醒的人数。
它仅适用于短字符串和少量人员。
我认为我需要在算法水平上进行一些改进。任何建议或暗示将不胜感激。 预先感谢。
import sys
import itertools
memo = {}
def wake(s, i):
if i in memo:
return memo[i]
s = list(s)
for n in i:
if n == 0:
s[n], s[n+1] = '.', '.'
elif n == len(s)-1:
s[n-1], s[n] = '.', '.'
else:
s[n-1], s[n], s[n+1] = '.', '.', '.'
memo[i] = s.count('.')
return memo[i]
if __name__ == '__main__':
with open(sys.argv[1]) as f:
line = f.readline()
n, k = map(int, list(line.rstrip().split(' ')))
line = f.readline()
s = line.rstrip()
ans = 0
for i in itertools.combinations(range(n), k):
temp = wake(s, i)
if temp > ans:
ans = temp
print(ans)
出于测试目的,我将在下面放置一些测试用例和正确答案。
Format:
n k
s
ans
5 3
.....
5
12 2
.SSSS.SS.SSS
9
7 1
..S.SS.
6
67 4
SS.S...S....SS..S..S.S.S...SS...SSS..SS.SS.SSSSS...S.S.S...S......S
48
29 2
.S.....SSSSS.SSSS...SS.SSS.SS
18
79 6
.S...SSS.SSS..SSSS.SSSSS.SS.S.SS.SS.SSSSSSS.SS...SS.S.SSS.SS.S.SS..S..S.SSS.SS.
47
41 9
.S.S...S.S.....S.SS.SS.SS.SS.S.SS.SS.....
41
91 67
...SS.SS....S...S.S.SS...SSS.SSSSSSS.....SS..S.S.SS...S..S..S.SS.......SSSSS.S.S...S.SS.S.S
91
7 97
SSSS.SS
7
276 23
SSSSSS.SSS..SSS.SS.S.SSSSSSSSSSSSSSSSSSSSSSSSSSSSSS.SS.SSSSSSSSSSSSSSSSSSS.SSSSSS.SSSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSS.S.SSS.SSSSSS.SSSSSSSSSSS.SSSSSSSSSSSSS.SSSSSSS.S.SSSS.SSSSSSSSSSSS.SSSSSSSSSSSSSSSS.SSS.S.SS.SSSSSSS.SSSSSSSS.SSS.S.
100
答案 0 :(得分:0)
如果我们先与dp[n][k]
个人打交道并且已经醒来的'S'
人,让n
是我们醒来的k
人的数量。对于dp[n][k]
,我认为没有理由唤醒人数n
,因为没有人n+1
我们可以唤醒(因为我们首先只处理n
人),因此更好地唤醒人n-1
,也使人n
醒来。我稍后会使用这种逻辑。
然后,如果n <= 3
,我们可以唤醒所有n
个人,只要我们有动静,即k > 0
。如果我们没有动作,那么答案就是已经醒着的人数。
如果n > 3
:
k = 0
,则为dp[n][k] = dp[n][0] = 0
,因为我们没有唤醒任何人。k > 0
,则dp[n][k] = max(dp[n - 3][k - 1] + s[n - 3 : n].count('S'), dp[n - 1][k])
。在这里,我们处理2种情况:如果我们唤醒了n-1
人,那么第n-2, n-1, n
个人醒了,输了1步,所以我们算出刚刚醒来的人数(s[n - 3 : n].count('S')
),并检查其余n-3
人和k-1
个动作的最大数量:dp[n - 3][k - 1]
。如果我们没有唤醒任何人,那么如果第n
人处于初始状态,那么我们还有k
个动作。因此,在这种情况下,答案为dp[n - 1][k]
。答案是max(dp[n][k]) + s.count('.')
:dp[n][k]
仅处理了熟睡的人数,但我们叫醒了他们。因此,要获得完整答案,我们只需添加已经醒着的人数。
ans = 0
if n <= 3:
if k > 0:
ans = n
else:
ans = s.count('.')
else:
dp = [[0 for x in range(k + 1)] for y in range(n)]
dp[2][1] = s[:3].count('S')
for i in range(3, n):
t = s[i - 3 : i].count('S')
for j in range(1, k + 1):
dp[i][j] = max(dp[i - 3][j - 1] + t, dp[i - 1][j])
for i in range(2, n):
ans = max(ans, dp[i][k])
ans += s.count('.')
print(ans)
答案 1 :(得分:0)
这是我的解决方法。
import pandas as pd
def count_all(text, string):
pos = string.find(text)
if len(string) == 0 or pos == -1:
return 0
return 1 + count_all(text, string[pos+len(text):])
def calculate_ans(input_str, k)->int:
if 'check':
if len(input_str) == 0 or \
(input_str.find('S') == -1 and input_str.find('.') == -1):
return 0
if k <= 0 or pd.isna(k):
return input_str.count('.')
for cur_str in ['SSS', 'S.S', 'ST.TS', 'SS', 'S']:
count_ns = min(count_all(cur_str, input_str), k)
if count_ns > 0:
if cur_str != 'S.S':
input_str = input_str.replace(cur_str, len(cur_str) * '.', int(count_ns))
else:
input_str = input_str.replace(cur_str, 'T.T', int(count_ns))
k -= count_ns
if k == 0:
break
return input_str.count('.') + input_str.count('T')
def carson_demo():
df = pd.read_csv('table.csv')
for index, (input_str, k, answer) in df.iterrows():
ans = 0 if pd.isna(input_str) else calculate_ans(input_str, k)
df.at[index, 'answer'] = int(ans) # update
df['answer'] = df['answer'].astype(int, errors='ignore')
df['k'] = df['k'].astype(int, errors='ignore')
df.to_csv('table.csv', index=False)
if __name__ == '__main__':
carson_demo()
table.csv(之前)
input_str,k,answer
.....,3,
.SSSS.SS.SSS,2,
..S.SS.,1,
SS.S...S....SS..S..S.S.S...SS...SSS..SS.SS.SSSSS...S.S.S...S......S,4,
.S.....SSSSS.SSSS...SS.SSS.SS,2,
.S...SSS.SSS..SSSS.SSSSS.SS.S.SS.SS.SSSSSSS.SS...SS.S.SSS.SS.S.SS..S..S.SSS.SS.,6,
.S.S...S.S.....S.SS.SS.SS.SS.S.SS.SS.....,9,
...SS.SS....S...S.S.SS...SSS.SSSSSSS.....SS..S.S.SS...S..S..S.SS.......SSSSS.S.S...S.SS.S.S,67,
SSSS.SS,97,
SSSSSS.SSS..SSS.SS.S.SSSSSSSSSSSSSSSSSSSSSSSSSSSSSS.SS.SSSSSSSSSSSSSSSSSSS.SSSSSS.SSSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSS.S.SSS.SSSSSS.SSSSSSSSSSS.SSSSSSSSSSSSS.SSSSSSS.S.SSSS.SSSSSSSSSSSS.SSSSSSSSSSSSSSSS.SSS.S.SS.SSSSSSS.SSSSSSSS.SSS.S.,23,
table.csv(之后)
input_str,k,answer
.....,3,5
.SSSS.SS.SSS,2,9
..S.SS.,1,6
SS.S...S....SS..S..S.S.S...SS...SSS..SS.SS.SSSSS...S.S.S...S......S,4,48
.S.....SSSSS.SSSS...SS.SSS.SS,2,18
.S...SSS.SSS..SSSS.SSSSS.SS.S.SS.SS.SSSSSSS.SS...SS.S.SSS.SS.S.SS..S..S.SSS.SS.,6,47
.S.S...S.S.....S.SS.SS.SS.SS.S.SS.SS.....,9,41
...SS.SS....S...S.S.SS...SSS.SSSSSSS.....SS..S.S.SS...S..S..S.SS.......SSSSS.S.S...S.SS.S.S,67,91
SSSS.SS,97,7
SSSSSS.SSS..SSS.SS.S.SSSSSSSSSSSSSSSSSSSSSSSSSSSSSS.SS.SSSSSSSSSSSSSSSSSSS.SSSSSS.SSSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSSSSS.SSSSSSSSSSSSSS.S.SSS.SSSSSS.SSSSSSSSSSS.SSSSSSSSSSSSS.SSSSSSS.S.SSSS.SSSSSSSSSSSS.SSSSSSSSSSSSSSSS.SSS.S.SS.SSSSSSS.SSSSSSSS.SSS.S.,23,100
答案 2 :(得分:0)
解决了Daniel算法中的一个小重叠问题。
ans = 0
if n <= 3:
if k > 0:
ans = n
else:
ans = s.count('.')
else:
dp = [[0 for x in range(k+1)] for y in range(n)]
dp[0][1] = s[:2].count('S')
dp[1][1] = s[:3].count('S')
dp[2][1] = max(s[:3].count('S'), s[1:4].count('S'))
for j in range(2,k+1):
dp[0][j] = dp[0][1]
dp[1][j] = dp[1][1]
dp[2][j] = s[:4].count('S')
for i in range(3,n-1):
for j in range(1,k+1):
dp[i][j] = max(dp[i-3][j-1] + s[i-1:i+2].count('S'),
dp[i-1][j])
for j in range(k+1):
dp[n-1][j] = dp[n-2][j]
ans = dp[n-1][k]
ans += s.count('.')
print(ans)