|
在2010年4月29号的直播中,xd=love提出了一个计算不同数量同种单位战斗之后优势方剩余数量的公式:
假设team A 的单位数为 M, team B 的单位数为 N,且 M>N。
则A队获胜之后的剩余单位数为:
$$\sqrt {M^2 - N^2}$$
这个简单的公式来自连续情形下的微分方程。但是现在用比较精确的算法来分析这个公式在星际里的可靠性。
下面说说我所采用的算法:
实际情况是比较复杂的,因为结果很大程度上会与操作有关。现在假设:双方都是良好的操作,即最大效率的每次集中火力点对方一个单位。
在这种假设之下,需要忽略一些次要因素,比如一次攻击输出总值大于对方生命值造成攻击浪费的情况。之所以可以先不考虑这个因素有两个原因,一是双方是公平的miss,2是这个忽略所造成的误差已经包含在了小数次数的攻击之中。在样本数量比较大的情况下,是可以描述真实情况的。(类似与阶梯函数被近似成连续函数的情形)
还有一个因素是剩下小数个单位时候如何处理,这里采取折中的方法,即保留小数个单位的存在,因为实际上在一个攻击周期中有个单位的血量是不满的,所以他相应的攻击输出就无法持续一个周期,因此“半个单位”这种处理其实与实际还是比较接近的。
假设每个单位一次有效攻击(已考虑防御的因素)为a,生命值为b。
则m个A队的单位在单位时间中对B队的伤害为 m*a;
由于在好的操作之下所有攻击集中在B队一个单位的身上,所以所需时间为 $t=\frac{b}{ma}$;
在这段时间中,B队对A队所产生的伤害是 $nat=\frac{nb}{m}$;
所以这段时间A队剩下的单位数量为 $\frac{mb-\frac{nb}{m}}{b}= m-\frac{n}{m}$; (可见最后的结果与a,b的值无关,也就是说与兵种无关!)
由此分析之后得到击毁第i个B队单位之后A队的剩余数量为:$m_{i+1}=m_i-\frac{n-i}{m_i}$;
不容易得到数列通项表达式,于是采用编程来得到结果:
#include <iostream>
#include <math.h>
#define M 12 // set original number of units in team A
int main()
{
std::cout << "Assume team A has more units than team B. " << std::endl;
std::cout << "The following 3 colomns give the original number of team B, the final number of team A, " <<
"and the final number according to the prediction from XD=love's formula." << std::endl;
for (int n = M; n != 0; --n) {
float m[n];
m[0] = M;
for(int i=0; i != n; ++i) {
m(i+1) = m(i) - ( n - i ) / m(i);
}
std::cout << n << '\t' << m[n] << '\t' << '\t' << sqrt ( M * M - n * n ) << std::endl;
}
return 0;
}
此程序同时计算了在一定A对数量的情况下,不同的B队初始数量造成的A队剩余结果。另外,还直接运用了大师的公式计算来比较两种算法的差异。
其中A队的初始数量假设为12个(在开头的#define M 中定义,可随意更改),程序运行结果如下:
(第一列是不同的B队初始值,第二列是相应的A队剩余数量,第三列是由大师的公式直接得到的结果)
Assume team A has more units than team B.
The following 3 colomns give the original number of team B, the final number of team A, and the final number according to the prediction from XD=love's formula.
12 0 0
11 4.24037 4.79583
10 6.15489 6.63325
9 7.52279 7.93725
8 8.58614 8.94427
7 9.44015 9.74679
6 10.1338 10.3923
5 10.6961 10.9087
4 11.1452 11.3137
3 11.4934 11.619
2 11.7488 11.8322
1 11.9167 11.9583
可见两种算法得到的结果十分接近,从而证明了大师那个相对比较简明的公式的可靠性。
------------------------------------
在此基础之上,其实很容易得到一些进一步的结果,那就是如果双方的兵种不对称会怎么样。
比如,相同数量,攻防不相同的大舰之间对战的结果会怎样?
采用类似的分析过程,只是a此时有两个值,a1和a2,比如3攻3防vs 0攻0防的话,a1=25+9-3=31,a2=25-6=19.
程序之中的核心部分$m_{i+1}=m_i-\frac{n-i}{m_i}$; 将变为:$m_{i+1}=m_i-\frac{\frac{(n-i)a_2}{a_1}}{m_i}$ :
新的结果如下:(A队12个高攻防)
The following 3 colomns give the original number of team B, the final number of team A, and the final number according to the prediction from XD=love's formula.
12 7.86227 0
11 8.6775 4.79583
10 9.32456 6.63325
9 9.9314 7.93725
8 10.4127 8.94427
7 10.784 9.74679
6 11.1433 10.3923
5 11.4064 10.9087
4 11.6637 11.3137
3 11.8328 11.619
2 11.9167 11.8322
1 12 11.9583
可见在B队 也有12个情况下,A队打赢之后还可以剩下7个左右。
当然实际情况中双方攻防不会差距这么大,比较多的是落后一级,例如A的3攻3防 vs B的2攻2防,此时a1=25+9-5=29,a2=25+6-6=25
结果如下:
The following 3 colomns give the original number of team B, the final number of team A, and the final number according to the prediction from XD=love's formula.
12 5.16354 0
11 6.7186 4.79583
10 7.88375 6.63325
9 8.80226 7.93725
8 9.54011 8.94427
7 10.1338 9.74679
6 10.6961 10.3923
5 11.1452 10.9087
4 11.4934 11.3137
3 11.7488 11.619
2 11.9167 11.8322
1 12 11.9583
也就是说一队打完还可以剩下5个左右。所以只差一级攻防的影响仍然是很大的。
另外附上大数量情况下的结果,假设A队原始量有100个:
Assume team A have more units than team B.
The following 3 colomns give the original number of team B, the final number of team A, and the final number according to the prediction from XD=love's formula.
100 0 0
99 13.4012 14.1067
98 19.2208 19.8997
97 23.6528 24.3105
96 27.3607 28
95 30.6021 31.225
94 33.5094 34.1174
93 36.1617 36.756
92 38.6105 39.1918
91 40.8917 41.4608
90 43.0315 43.589
89 45.0495 45.5961
88 46.9615 47.4974
87 48.7795 49.3052
86 50.5136 51.0294
85 52.172 52.6783
84 53.7616 54.2586
83 55.2884 55.7763
82 56.7571 57.2364
81 58.1723 58.643
80 59.5377 60
79 60.8566 61.3107
78 62.1319 62.578
77 63.3661 63.8044
76 64.5618 64.9923
75 65.7208 66.1438
74 66.8452 67.2607
73 67.9365 68.3447
72 68.9965 69.3974
71 70.0264 70.4202
70 71.0274 71.4143
69 72.001 72.3809
68 72.9481 73.3212
67 73.8698 74.2361
66 74.7669 75.1266
65 75.6403 75.9934
64 76.4909 76.8375
63 77.3194 77.6595
62 78.1264 78.4602
61 78.9127 79.2401
60 79.6788 80
59 80.4253 80.7403
58 81.1528 81.4616
57 81.8617 82.1645
56 82.5525 82.8493
55 83.2257 83.5165
54 83.8817 84.1665
53 84.5209 84.7998
52 85.1436 85.4166
51 85.7502 86.0174
50 86.3411 86.6025
49 86.9166 87.1722
48 87.4769 87.7268
47 88.0223 88.2666
46 88.5532 88.7919
45 89.0698 89.3029
44 89.5722 89.7998
43 90.0609 90.2829
42 90.5359 90.7524
41 90.9975 91.2086
40 91.446 91.6515
39 91.8814 92.0815
38 92.304 92.4986
37 92.7139 92.9032
36 93.1113 93.2952
35 93.4963 93.675
34 93.8693 94.0425
33 94.2301 94.3981
32 94.579 94.7418
31 94.9162 95.0737
30 95.2417 95.3939
29 95.5557 95.7027
28 95.8582 96
27 96.1494 96.286
26 96.4294 96.5609
25 96.6983 96.8246
24 96.9562 97.0773
23 97.2031 97.3191
22 97.4391 97.55
21 97.6644 97.7701
20 97.879 97.9796
19 98.0829 98.1784
18 98.2762 98.3667
17 98.459 98.5444
16 98.6314 98.7117
15 98.7933 98.8686
14 98.945 99.0152
13 99.0862 99.1514
12 99.2173 99.2774
11 99.3381 99.3932
10 99.4487 99.4987
9 99.5491 99.5942
8 99.6395 99.6795
7 99.7197 99.7547
6 99.7898 99.8198
5 99.8499 99.8749
4 99.9 99.92
3 99.94 99.955
2 99.97 99.98
1 99.99 99.995
可见依然吻合的很好。
结合昨天教主与mvp决战时候的情况,由于教主本身被点掉一些单位并且又有一些单位脱节,假设当时mvp有18个大舰,教主少了5个。那么结果是:
13 12.0519 12.4499
也就是mvp剩下了一队,比较吻合当时的情况。
其实程序本身很简单的,主要问题在于分析算法,做出合理的近似。
我看了一下wiki上对Lanchester's Square Law的解释,不过好像没有讲原因,所以有可能是数据拟合出来的经验公式。而且后面还有
In modern warfare, to take into account that to some extent both linear and the square apply often a factor of 1.5 is used.
那就不太符合星际的情况了。
这是兰切斯特平方率的实际应用,适用于远程兵种交锋,不过在公式中还要考虑武器质量,这个就复杂多了
兰切斯特法则:
假设某一次交手的时候我方投入的人数是 M 人,敌方 N 人。并假设我方平均每个人在单位时间内可以使敌方 p 人丧失战斗力,敌方平均每个人在单位时间内可以使我方 q 人丧失战斗力。
假定在 t 时刻,我方剩下的人数是 m(t) 人,敌方剩下 n(t) 人,那么在这个时刻,敌方被我方杀伤的人数必定是我方此时的总人数乘以我方单兵作战能力,即
$$\frac{{\rm d}n(t)}{{\rm d}t}=-pm(t),--(方程1)$$
$$\frac{{\rm d}m(t)}{{\rm d}t}=-qn(t).--(方程2)$$
$$n_0=N,m_0=M--(初值)$$
求解,得
$$m(t) = \frac{1}{2} [(M-N\sqrt{\frac{q}{p}})e^{\sqrt{pq}t}+(M+N\sqrt{\frac{q}{p}})e^{-\sqrt{pq}t}],$$
$$n(t) = \frac{1}{2} [(N-M\sqrt{\frac{p}{q}})e^{\sqrt{pq}t}+(N+M\sqrt{\frac{p}{q}})e^{-\sqrt{pq}t}].$$
结论1:我方取胜的条件是:
$$M\sqrt{p}>N\sqrt{q}$$
人数如果变为原来的2倍,战斗能力是原来的4倍,这就是著名的平方战斗定律
结论2:假定我方与敌方的单人的战斗力一样,即 p = q 的情况下,如果 m > n,那么到战斗结束,敌人一个死光,我方还剩下$\sqrt{M^2 - N^2}$人,我方总共死$M - \sqrt{M^2 - N^2}$人。
严格数学证明(By:castelu):
$$\frac{{\rm d}n}{{\rm d}t}=-pm$$
$$\frac{{\rm d}m}{{\rm d}t}=-qn$$
上下两式分别求微分以后代入,得到:
$$\frac{{\rm d}^2n}{{\rm d}t^2} = pqn$$
$$\frac{{\rm d}^2m}{{\rm d}t^2} = pqm$$
这是二阶常系数线性微分方程,特征方程是:
$$r^2-pq=0$$
于是通解为:
$$m=C_1e^{\sqrt {pq}t}+C_2e^{-\sqrt {pq}t}$$
$$n=C_3e^{\sqrt {pq}t}+C_4e^{-\sqrt {pq}t}$$
根据初值条件:
$$m_0=M$$
得到:
$$m=C_1e^{\sqrt {pq}t}+(M-C_1)e^{-\sqrt {pq}t}$$
求微分后代入原方程组中的2式,解得:
$$C_1=\frac{1}{2}[M-N\sqrt {\frac{q}{p}}]$$
于是:
$$m =\frac{1}{2}[(M-N\sqrt {\frac{q}{p}})e^{\sqrt {pq}t}+(M+N\sqrt {\frac{q}{p}})e^{-\sqrt {pq}t}]$$
$$n =\frac{1}{2}[(N-M\sqrt {\frac{q}{p}})e^{\sqrt {pq}t}+(N+M\sqrt {\frac{q}{p}})e^{-\sqrt {pq}t}]$$
假如p=q,则:
$$m=\frac{1}{2}[(M-N)e^{pt}+(M+N)e^{-pt}]$$
$$n=\frac{1}{2}[(N-M)e^{pt}+(N+M)e^{-pt}]$$
当n=0时,对于通解中的2式:
$$(N+M)e^{-pt}=-(N-M)e^{pt}$$
$$M+N = (M-N)e^{2pt}$$
$$\ln (M+N)=\ln (M-N)+2pt$$
$$t=\frac{1}{2p}\ln \frac{M+N}{M-N}$$
对于通解中的1式:
$$m =(M-N){e^{pt}}$$
$$=(M-N)e^{\frac{1}{2}\ln \frac{M+N}{M-N}}$$
$$=(M-N)\sqrt {\frac{M+N}{M-N}}$$
$$=\sqrt {M^2-N^2}$$
证毕
模型的意义在于能够还原,越是复杂的模型就越接近真实的情况,不能因为真实条件下不会出现此类情况就去否定一个模型,事实上Lanchester模型对于星际的作用还是很大的,这也就是为什么职业选手从不用4个xx打5个xx或者8条狗打10条狗的原因!
连续应该是可以自洽的,因为这个是常微分方程
数字上的结果在细节上略有出入是因为实际情况终归是离散的,这样的话在不断缩短的每个周期中就要被打掉的那个单位能否成功打出那一下是只能用概率表示,要足够符合需要样本数量够大。但总之还是吻合的相当好了。
假设是对于同种族同兵种应该是有很好的吻合的,但是对于不同种族或者不同兵种之间的较量的话,该理论就必须得扩展了。
比如你说"可见最后的结果与a,b的值无关,也就是说与兵种无关!"也就是说与攻击力和血长度无关。但是实际的情况是这样的吗?一队狗与一队叉子去打,按照你的理论,二者如果操作都很完美的话,最后应该全部死光,但是实际情况可能吗?
所以说这个地方不能说与兵种无关,兵种在方程中提供了非常重要的权重,这也是为什么打星际光是单一兵种是很难解决战斗的关键因素。
当然了你计算的这个还是有意义的,对于同种族同兵种的较量给了大家一些对于操作上的数据证明。
另外对于权重,我觉得你应该再深入的探讨一下,这个对于实际就更有意义了,例如:我觉得兵种权重可以这样定义:攻击力 * 血长度 * C / 攻击频率, C为一常量,这里先计算地面攻击,C这里我就取C = 1了,因为我也不知道取什么值好,现在列出一些兵种权重:
小狗(未升级攻击频率前):5 * 35 * (1 / 8) =21.875
小狗(升级攻击频率后):5 * 35 * (1 / 6) =29.167
刺蛇(升级射程后):10 * 80 * (1 / 15) = 53.333
飞龙:9 *120 * (1 / 30) = 36
Lurker: 20 * 125 * (1 / 37) = 67.568
大象:20 * 400 * (1 / 15) = 533.333
守护者:20 * 150 * (1 / 30) = 100
吞噬者:25 * 250 * (1 / 100) = 62.5
狂战士:16 * 160 * (1 / 22) = 116.364
龙骑:20 * 180 * (1 / 30) = 120
闪电:100(闪电风暴) * 80 * (1 / 75) = 106.667
Dark:40 * 120 * (1 / 30) = 160
金甲:100 * 180 * (1 / 60) = 300
Scout:28 * 250 * (1 / 22) = 318.189
海盗船:5 * 180 * (1 / 8) = 112.5
人族的就不列了。
现在举几个例子:
1、一队狗和一队叉子。加上权重计算得到:叉子剩下= 10.717,也就是11个,符合实战。如果要全歼一队叉子,那么需要多少只狗呢?计算得到:未升级攻击频率需要28只,升级后需要24只。
2、一队口水和一队叉子(肉搏)。计算得到:叉子剩下=8.58,8个左右。要全歼一队叉子需要18个口水。
3、一队小狗和一队龙骑。因为龙骑打小狗减半,所以计算得到:龙骑剩下=9.371,但是要全歼一队龙骑则只需要20只狗即可。
这三个例子都符合实战。小狗克龙骑也可以看到。提速xx打口水也并不吃亏的。当然了实际操作中肯定有很多的变数的,例如口水的操作,龙骑的操作等等。而且如果权重加上射程,是否有飞溅效果等因素则更加合理。
以上就是一些关于权重的个人心得,还望有抛砖引玉之作用啊。
下面附上计算全歼对方需要的数量程序:
#define M 12 //为一队的数量
int i, n;
n = 1;//n为需要的数量的变量
float q = M;
while (q > 0)
{
q = M;
i = n;
while (q > 0 && i > 0)
{
q = q - i * StrToFloat(Edit1->Text) / (q * StrToFloat(Edit2->Text)); //参考m(i+1) = m - ( n - i ) / m得到
i = i - 1;
}
n = n + 1;
}
ShowMessage(n - 1);
以上代码在C++Builder 2007上测试通过。
还有一个典型的例子就是海盗船和飞龙。一队飞龙打一队海盗船,不考虑飞溅和子弹弹射攻击的话,海盗船应该还剩下9个左右,所以很难看到飞龙去打同等数量或者只是少很好数量的海盗船的。一般都是一群飞龙围着海盗船打。
对于不同的对抗,要分别计算dps,也就是各有不同的a1,a2,b1,b2,这样显然在式子里是不会消掉的。
因为攻防和体积的问题,同样一个单位,在面对不同的对手时a1 a2的值都不相同。
落实到p和z的单位,又有回护甲和回血的问题,就会让问题很复杂,所以就先考虑最简单的情况了,这就是为什么用t的大舰来举例。
另外如果是肉搏单位,就完全不能用这个理论套,因为齐射的假设无法成立,要完全用另一套模型才行。 |
|