【博弈论+dp】海盗分钱币问题

经典的海盗分钱问题,原题在这里有描述:http://edward-mj.com/page/2


动态规划方案:

m个海盗

n[i][j] : 保存当由海盗i来分钱时,海盗j能得到的钱数(j>=i)

然后 在海盗i-1分钱时,当且仅当 分给海盗j( j>i )的钱数n[i-1][j]  > n[i][j],才能够获得海盗j的支持。 

注意,考虑一种复杂情况,当用户i 分钱怎么分都是死的时候,可以设置n[i][i] = -1. 即看作用户i只要保命就行。这种情况下,就算i-1不给i钱,i也会支持i-1. 因此n[i-1][i] =-1+1=0即可。而设置 n[i][j(j>i)]=n[i+1][j],即因为海盗i必死,所以海盗j能够获得的钱数将由i+1海盗决定

于是,对i-1海盗: 

  • TN(总钱数) = n[i-1][i-1] + sum( n[i-1][j] = n[i][j] +1 or 0,  j=1~m, j!=i-1 ), 并要求取n[i][j]+1的次数>=(m-i+2)/2 
  • 如果上述方案不存在,则 n[i-1][i-1]=-1(无法保命), n[i-1][j (j>i-1) ] = n[i][j]

n[ m ] [ m ]= TN(如果只剩下一个海盗m,则他将获得所有金币)
for  i=m-1 to 1:
     memset( num , -1, sizeof...
     num[w=0]=v=0 //w 为获得票数(不包括自己),v 为需要的金币数量
     for  j = i+1 to m:
         for w = m-k+1 to 1:
             if num[w] == -1 or num[w] > num[w-1] + n[i+1][j] :   
                 lst[w]=j, num[w]=..... //获得j的支持,获得w票
     if  num[ (m - i + 2) /2 ] != -1 && num[ (m - i + 2) /2 ] <= TN:  / /存在分配方案
         for j = i+1 to m: 
             n[i][j] = n[i+1][j] + 1 or 0   //每个海盗d的金币数量
         n[i][i] =

你可能感兴趣的:(hihocode,脑洞)