尤拉計劃701:隨機連線區域

lt發表於2020-02-09

考慮一個由正方形單元格組成的W × H矩形,每個單元格的面積為1。 每個單元格以概率為0.5獨立地塗成黑色,否則為白色。 假設共享一個邊緣的黑色單元已連線。 考慮連線單元的最大面積。 定義E(W,H)為該最大面積的期望值。 例如, E(2,2) = 1.875,如下圖所示。

2x2
已知E(4,4) = 5.76487732,四捨五入到小數點後8位。
求E(7,7),四捨五入到小數點後8位。

畫圖程式:

n=3
m=2
def e(n,m):
 g=2**(n*m)
 ch='□■'
 for i in range(0,g):
  print("area",i)
  s=bin(i+g)[3:]
  x=0
  for j in s:
   x+=1
   print(ch[int(j)],end='')
   if x==n:print('');x=0    

使用並查集實現的演算法,算4x4要5秒

class UnionFind(object):
    """並查集類"""
    def __init__(self, n):
        """長度為n的並查集"""
        self.uf = [-1 for i in range(n + 1)]    # 列表0位置空出
        self.area = [1 for i in range(n + 1)]    #某個根的集合面積 列表0位置空出
        self.sets_count = n                     # 判斷並查集裡共有幾個集合, 初始化預設互相獨立
        self.s=[]
    def find2(self, p):
        """查詢p的根結點(祖先)"""
        r = p
        while self.uf[p] > 0:
            p = self.uf[p]
        while r != p:
            self.uf[r], r = p, self.uf[r]
        return p
    def find(self, p):
        """尾遞迴"""
        if self.uf[p] < 0:
            return p
        self.uf[p] = self.find(self.uf[p])
        return self.uf[p]
    def union(self, p, q):
        """連通p,q 讓q指向p"""
        proot = self.find(p)
        qroot = self.find(q)
        if proot == qroot:
            return
        elif self.uf[proot] > self.uf[qroot]:   # 負數比較, 左邊規模更小
            self.area[qroot]+=self.area[proot]
            self.uf[qroot] += self.uf[proot]
            self.uf[proot] = qroot
        else:
            self.uf[proot] += self.uf[qroot]  # 規模相加
            self.area[proot]+=self.area[qroot] 
            self.uf[qroot] = proot

        self.sets_count -= 1                    # 連通後集合總數減一
    def is_connected(self, p, q):
        """判斷pq是否已經連通"""
        return self.find(p) == self.find(q)     # 即判斷兩個結點是否是屬於同一個祖先

def setcolor(w,h):
  totalarea=0
  g=2**(w*h)
  ch='□■'
  color=[0]*(w*h+1)
  for  i  in  range(0,g):  #遍歷每種圖案
    b=bin(i+g)[3:]
    x=0
    x1=0
    for  j  in  b:
      x+=1
      x1+=1
      color[x]=j    #按二進位制數填充當前顏色
      #print(ch[int(j)],end='')
      #if  x1==w:print('');x1=0  
    uf=UnionFind(w*h)  #並查集物件
    #uf.js(w,h)
    #print(i,uf.s)
    for  j  in  range(1,w*h+1):
      #把每格分配到集合,然後取area最大的值
      #if  color[j]=='1':uf.add(j,color)
      if color[j]=='1' and (j-1)%w>0 and j-1>0 and not uf.is_connected(j,j-1) and color[j]==color[j-1]: uf.union( j,j-1) 
      if color[j]=='1' and j-w>0 and not uf.is_connected(j,j-w) and color[j]==color[j-w]: uf.union( j,j-w)     #顏色相同的相鄰格加入同一個集合
    #print(i,"==>",color,  end='  ')
    maxarea=0
    for  j  in  range(1,w*h+1):
      if  color[j]=='1'  and  uf.area[j]>maxarea:  maxarea=uf.area[j]
    totalarea+=maxarea
    #print(i,"==>",maxarea,uf.area,uf.uf,'\n')
  return  totalarea/g


w,h=4,4


import time
tm=time.time()
print(setcolor(w,h),time.time()-tm)

5.7648773193359375 4.237565040588379

相關文章