奴隸主在場時克蘇恩打死對方的概率如何計算?

對面10血英雄,其場上有一個3血的奴隸主,我方此時上一個15攻的克蘇恩打死對面英雄的概率是多少?


20170325 發現之前程序有問題,進行了修改,思路是一樣的,結果略有差別,抱歉

新程序見

奴隸主在場時克蘇恩打死對方的概率如何計算? - 知乎

----------------------------------------分割線----------------------

爐石下面怎麼這麼多概率題。。。
先上結論 0.675933% 和其他答主模擬的結論差不多

首先明確:
1.奴隸主受到攻擊未死亡會生一個新的滿血奴隸主
2.奴隸主死亡不消失
3.場面上最多7個奴隸主

然後建立函數f(a,b,c,d)表示當前場面 a個3血,b個2血,c個1血,d個0血奴隸主的概率

分三種情況

1.a+b+c+d&>7 即總的奴隸主個數大於7,這是不可能發生的,概率為0

2.a+b+c+d&<7 即非一血奴隸主受到傷害會生新的奴隸主

3.a+b+c+d=7 即滿場面,不會生新的奴隸主

三種情況分別建立狀態轉移方程(狀態轉移方程一會放上來)

初始條件f(1)(0)(0)(0)=1 即開始時只有一個3血奴隸主

然後將f計算15次,每次判斷是否能擊殺,將可擊殺概率累加,得到結果

#include &
#include &
#include &
using namespace std;

struct gl
{
double a[10][10][10][10];
};
gl f,p;
int i,j,k,l,m,n;
double sum,ans;

int main()
{
f.a[1][0][0][0]=1;
ans=0;
for (n=1;n&<=15;n++) { for (i=0;i&<=7;i++) for (j=0;j&<=7;j++) for (k=0;k&<=7;k++) for (l=0;l&<=7;l++) { double sum=0; if (i+j+k+l&>7) sum=0;
if (i+j+k+l==7)
{
m=i+j+k;
if (j&>0) sum+=1.0*(i+1)/(m+1)*f.a[i+1][j-1][k][l];
if (k&>0) sum+=1.0*(j+1)/(m+1)*f.a[i][j+1][k-1][l];
if (l&>0) sum+=1.0*(k+1)/(m+1)*f.a[i][j][k+1][l-1];

if (j&>0) sum+=1.0*(i)/m* f.a[i][j-1][k][l];
if (i&>0 k&>0) sum+=1.0*(j+1)/m* f.a[i-1][j+1][k-1][l];
if (l&>0) sum+=1.0*(k+1)/(m+2)* f.a[i][j][k+1][l-1];
}
if (i+j+k+l&<7) { m=i+j+k; if (j&>0) sum+=1.0*(i)/m* f.a[i][j-1][k][l];
if (i&>0 k&>0) sum+=1.0*(j+1)/m* f.a[i-1][j+1][k-1][l];
if (l&>0) sum+=1.0*(k+1)/(m+2)* f.a[i][j][k+1][l-1];

}
p.a[i][j][k][l]=sum+f.a[i][j][k][l]/(i+j+k+1);
if (j+2*k+3*l==n-10) {ans+=p.a[i][j][k][l]; p.a[i][j][k][l]=0;}
}
f=p;
}
cout&<&


致死概率:0.00675933495588689, 即為0.6759% 看來下別的答主都是採用模擬N萬次,再統計死亡場次.而我是直接計算的死亡概率. 所以如果概率策略沒出現bug,相對而言我的是最精準的(因為還存在浮點數計算時候的誤差).歡迎各路大神指點.

補充一個條件:

死亡結算要在戰吼結算之後

在克蘇恩攻擊期間打死一個奴隸主,是不會出現空位的,只會在場上變成一個3/0的奴隸主"占"著位置 . 也就是如果一個奴隸主最多吸收 7*3 = 21點傷害. 如果是一個51血克蘇恩 必打臉30血以上

剩餘血量 : 概率

dead: 0.00675933495588689,

1: 0.009080937813881385,

2: 0.01949495243192154,

3: 0.039872530626527014,

4: 0.07587846997012054,

5: 0.12891580434253652,

6: 0.18679904830022542,

7: 0.21733531193947417,

8: 0.18648510730473927,

9: 0.10271684398913593,

10: 0.0266616583305744,

下面是python源碼, 我跑15次攻擊共用時 27m57s

# encoding=utf-8
from collections import Counter
import Queue
# string 第N輪攻擊|主角血量|隨從血量|局面數量
# origin_string = 0|10|3444444|1
# 4

def strinc(string):
return str(int(string) + 1)

def strdec(string):
return str(int(string) - 1)

def attack_Patron(Patronstring, index):
Patronlist = map(int, list(Patronstring))
Patronblank = None
for i in range(0, 6):
if Patronlist[i] == 4:
Patronblank = i
break
Patronlist[index] -= 1
# 如果受傷的奴隸沒有死亡,並且場面有空位則在空位召喚一個新的奴隸主
if Patronlist[index] &> 0 and Patronblank is not None:
Patronlist[Patronblank] = 3
Patronlist = sorted(Patronlist, reverse=True)
rtnstring = "".join(map(str, Patronlist))
return rtnstring

def CThun_attack(deep, health, Patronstring, num):
num = float(num)
d = Counter()
Patronsum = 1.0
for i in range(0, 7):
if Patronstring[i] != "0" and Patronstring[i] != "4":
Patronsum += 1
# print Patronsum

# 打臉
tmpstring = strinc(deep) + "|" + strdec(health) + "|" + Patronstring
d.update({tmpstring: num / Patronsum})
# 打隨從
for i in range(0, 7):
if Patronstring[i] != "0" and Patronstring[i] != "4":
newPatronstring = attack_Patron(Patronstring, i)
tmpstring = strinc(deep) + "|" + health + "|" + newPatronstring
d.update({tmpstring: num / Patronsum})
rtnlist = []
for k, v in d.items():
rtnlist.append(k + "|" + str(v))
return rtnlist

def util():
origin_string = "0|10|3444444|1.0"
q = Queue.Queue(maxsize=-1)
q.put(origin_string)
attach_num = 15
while True:
nowstring = q.get()
# print "parse", nowstring
deep, health, Patronstring, num = nowstring.split("|")
if int(deep) &>= attach_num:
q.put(nowstring)
break
appendstring = CThun_attack(deep, health, Patronstring, num)
# print "put", appendstring
for i in appendstring:
# print "put %s" % i
q.put(i)
count = Counter()
while not q.empty():
string = q.get()
# print string
deep, health, Patronlist, num = string.split("|")
if int(health) &<= 0: health = "dead" count.update({health: float(num)}) print count util()


鑒於奴隸主是被打一下就會多一個,也就是說你打對面10下(一下都沒有打到奴隸主全打對面臉上把對面打死),一下都不可以碰到奴隸主。你碰到一下就多一個三血的怪在場上,而且前一個兩血的怪還是不可以碰的,碰到會再多一個3/3!

也就是說你不是在搏15下傷害分配到13滴血上,而是在賭你前10下沒一下打在奴隸主身上,因為一旦你打到第一下,場上就是兩個怪+10滴血,不但多了分攤傷害,打不死的幾率也是遞增的,打死對面英雄的幾率就更低了。

這種情況上克蘇恩獲勝那幾乎是微乎其微的,說白了1,奴隸主的特效太坑,2,對面英雄血太多了,還沒有到斬殺。

如果對面英雄就3滴血垂死了我建議你試一下,三滴血以上你別試了,而十滴血能打死的幾率堪稱火星撞地球。而且可能你的下一個回合就崩掉了。

就不能解掉奴隸主再出克蘇恩么??


你下完之後迅速點結束回合 對面的下回合可能因為動畫太長導致無法操作 來不及解掉你的克蘇恩 你可以大搖大擺地踢過去


上課無聊寫了個小程序跑了一下,大約0.645%

不要吐槽我的截圖方式_(:_」∠)_也不要吐槽彩筆的代碼_(:_」∠)_


根據貼吧常識,概率大概是50%吧,畢竟只有兩種結果:打得死,打不死。


用我的親身經歷告訴你,克蘇恩應該怎麼用,

自從爸爸狠心削弱了德魯伊後,我作為一個把咆哮德當信仰的人怎麼會甘心偉大的瑪法里奧就此沉淪滾回翡翠夢境睡大覺,於是乎我分解了知識古樹,分解了老鹿,分解了貓頭鷹等等後毅然決然合了一套克蘇恩德,為了證明德魯伊是適合這個版本的我開始了天(zuo)梯(si)之路

在發牌員不屑的眼神下,我充分證明了德魯伊已經不適合這個版本(啪啪啪),不,我不是一個一蹦到底的人,我毅然決然繼續點下了開始的按鈕,我不是因為別的,我就是要告訴你們一個信仰自然的德魯伊是不會被打敗的,此時耳邊響起「格魯什 對陣 瑪法里奧」

excuse me?你他喵的不是在逗我,不是我謙虛,我一個小德怎麼就遇到奴隸戰了呢,我當時就念了2句詩:去你丫的奴隸戰,玩奴隸戰的人全家XXXX。

下面有請我們的前部落大酋長來講一講當時發生了什麼

格魯什:咳咳,額

「所有人,都過來」

「所有人,都過來」

「所有人,都過來」

「所有人,都過來」

「所有人,都過來」

「所有人,都過來」

好的我說完了

當時的我是一臉生無可戀的表情,但是,我卻在下一回合抽到了克蘇恩,突然我發現對面雖然滿場奴隸主但是有一個致命的問題,因為場上7隻怪(6個奴隸主+苦痛)所以不會用新生的奴隸主,我的克蘇恩可以打17點,也就是說,我有機會解掉對面場面的情況下不會新生出奴隸主,於是乎我慢慢的用滑鼠拖起上古之神(此時王的BGM響起)咣,大地因為上古之神的到來震了一下,古神開始發力

下面我們還是請前大酋長講講當時發生了什麼:

格魯什:」所有人,都過----------咦,人呢, @所有人「

是的,克蘇恩把場面解了,對面只有1個滿血的奴隸主,其餘的奴隸主以及苦痛都被強大的古神解掉了,隨後戰士因為無力鋪第二波只能「我選擇死亡,我要粉碎你!」

克蘇恩:我不止針對你,我是說在座的各位,都是辣雞。

題主,你學到了么?

以上


其他程序都錯了,概率沒你們算的那麼高。

錯誤主要有兩點。

1.沒考慮隨從最多7個

2.沒考慮奴隸主1血就死了

所以你們的答案只算是近似結果的近似結果。

近似結果0.692%

以下用MATLAB暴力模擬100000次戰吼結果統計:

橫軸是克蘇恩吼完英雄剩餘血量。

看起來還是挺漂亮的,嗯~附源程序

clear;clc;
count = 0; %成功次數
for a=1:100000
waitbar(a/100000)
n = 1; %場怪數
blood = zeros(1,8); %初始化敵方面板血槽
blood(1) = 10; %英雄初始10血
blood(2) = 3; %第一個奴隸主血量

for w=1:15 %初始化
num = numel(blood(blood~=0)); %敵方單位數量
k = rand(1,num); %偽隨機數列
[C I] = max(k); %設隨機序列最大值為飛彈擊中目標
blood(I) = blood(I) - 1; %擊中目標血量-1
if I&>1 %未擊中英雄開始如下判定
if blood(I)&>0 %奴隸主未死亡
if num&<8 blood(num+1)=3; %場面未滿產生新奴隸主 end else %奴隸主死亡 for i=I:7 blood(i)=blood(i+1); %其他奴隸主左移 end blood(8) = 0; %留出新空位 end else %擊中英雄 if blood(1)&<1 count = count + 1; %成功一次 break %跳出本次循環 end end end res(a,:)=blood; %歷次模擬結果 end result=count./100000 cnt=res(:,1)"; for i=1:11 rr(i)=length(find(cnt==(i-1))); end name={"0","1","2","3","4","5","6","7","8","9","10"}; bar(rr); set(gca, "XTickLabel", name);

注釋寫的很清楚了,應該看的懂。有條件自己跑一下,詳細結果數組是res。

有不對的地方請指出,反正我是沒找出來。


程序模擬了一下,大概2.6%的樣子能贏,比想像中的高呀。。

&