0300 蛋白质折叠
* * * *
拉格朗日计划
* * * *
蛋白质折叠

可以将蛋白质简单地想象成由疏水成分H和极性成分P构成的串,例如HHPPHHHPHHPH。

本问题中,蛋白质的方向是重要的,因此HPP和PPH是不同的蛋白质,从而由n个成分组成的不同蛋白质一共有$2^n$种。

自然界中这些串一般都会折叠起来,使得H-H的接触点尽可能多,因为这在能量上有优势。

这就导致H成分倾向于聚集在中间部分,而P成分则留在外围。

天然蛋白质当然是在三维空间中折叠,不过此处为了简化模型只考虑二维折叠的情况。

下图中展示了上例蛋白两种可能的折叠方式(H-H接触点用红色点表示)。



左边的折叠方式只有6个H-H接触点,它不可能自然生成。而右边的折叠方式有9个H-H接触点,也是该蛋白的最优折叠方式。

假定H成分和P成分在串的所有位置都等可能出现,则对长度为8的蛋白质串,最优折叠方式中H-H接触点的平均数量是$850/28=3.3203125$。

求长度为15的蛋白质串最优折叠方式中H-H接触点的平均数量?答案是有限小数,请写出其精确的数值。

本题难度:



解答

本题除了枚举+回溯以外似乎也没什么好方法。

考虑一个$30\times 30$的格子,前两格位于中间且呈固定的方向,记录当前串的长度、串尾坐标以及串中的成分的接触情况(用位或运算表示第i位和第j位接触)。

使用深度优先搜索尝试填入格子并回溯以得到所有可能的序列接触情况。

最后,再次枚举序列并统计对应的接触数,最终结果是$8.0540771484375$。

注:为便于作除法,以下为Python 3代码。

def tryOut(t,u,v,s):
  for x,y in [(u-1,v),(u+1,v),(u,v-1),(u,v+1)]:
      if b[x][y]!=-1:
          s|=1 << g[t-1][b[x][y]]
  if t==target:
      p.add(s)
  else:
      for x,y in [(u-1,v),(u+1,v),(u,v-1),(u,v+1)]:
          if b[x][y]==-1:
              b[x][y]=t
              tryOut(t+1,x,y,s)
              b[x][y]=-1

target=15
g=[[-1]*target for i in range(target)]
b=[[-1]*(target*2+1) for i in range(target*2+1)]
rp=[0]*(1 << target)
mx=[0]*(1 << target)

p=set()
m=0
for i in range(0,target,2):
  for j in range(1,target,2):
      g[i][j]=g[j][i]=m
      m+=1
b[target][target]=0
b[target][target+1]=1
tryOut(2,target,target+1,g[0][1])

q=[]
for s in sorted(p,reverse=True):
  i=0
  while q and i < len(q) and q[i]|s!=q[i]:
      i+=1
  if i==len(q):
      q.append(s)
  
res=0
for s in range(1 << target):
  rp[s]=((rp[s//2]//2))|((s%2) << (target-1))
  if rp[s] < s:
      res+=mx[rp[s]]
  else:
      y=0
      for i in range(0,target,2):
          for j in range(1,target,2):
              if (s>>i)%2==(s>>j)%2==1:
                  y|=1 << g[i][j]
      for x in p:
          mx[s]=max(mx[s],format(x&y,"b").count('1'))
      res+=mx[s]

print(res/(1 << target))