P5415
SOL
对于我这样的“wen” “mang”,这题意可能有点太简略了。。
参照了 @ i_m_a_大佬的题解才理解题意。。
简述一下题意:
每次选出序列的前4个,从中等概率产生一个赢家,留在原地,剩下三个按照原来的相对位置挪到序列末尾。依次循环,知道有一个人连续赢了m场,游戏结束。问初始序列中第k位置的人(我们称作目标点)连续赢m次的概率。
用高斯消元求出概率dp方程式
不难发现,我们只需要关注当前的赢家(在第一个位置)连续赢了多少次,以及目标点的位置。
f
[
i
]
[
j
]
表
示
目
标
点
在
i
,
1
号
点
连
续
赢
了
j
次
的
概
率
f[i][j]表示目标点在i,1号点连续赢了j次的概率
f[i][j]表示目标点在i,1号点连续赢了j次的概率。
对于 j = = m j==m j==m,即边界,只有 f [ 1 ] [ m ] = 1 , 其 余 为 0 f[1][m]=1,其余为0 f[1][m]=1,其余为0
对于
0
≤
j
<
m
0\le j \lt m
0≤j<m,有三种情况:
1.目标点在一号点,
f
[
1
]
[
j
]
=
f
[
1
]
[
j
+
1
]
∗
1
4
+
f
[
n
]
[
1
]
∗
3
4
f[1][j]=f[1][j+1]*\frac{1}{4}+f[n][1]*\frac{3}{4}
f[1][j]=f[1][j+1]∗41+f[n][1]∗43
2.目标点在
2
−
4
2-4
2−4,
f
[
2
]
[
j
]
=
f
[
1
]
[
1
]
∗
1
4
+
f
[
n
−
2
]
[
j
+
1
]
∗
1
4
+
f
[
n
−
1
]
[
1
]
∗
1
2
f[2][j]=f[1][1]*\frac{1}{4}+f[n-2][j+1]*\frac{1}{4}+f[n-1][1]*\frac{1}{2}
f[2][j]=f[1][1]∗41+f[n−2][j+1]∗41+f[n−1][1]∗21
(
3
,
4
3,4
3,4类似)
3.目标点在
5
−
n
5-n
5−n,
f
[
i
]
[
j
]
=
f
[
i
−
3
]
[
j
+
1
]
∗
1
4
+
f
[
i
−
3
]
[
1
]
∗
3
4
f[i][j]=f[i-3][j+1]*\frac{1}{4}+f[i-3][1]*\frac{3}{4}
f[i][j]=f[i−3][j+1]∗41+f[i−3][1]∗43
显然这是有环的,由于方程总数为
n
∗
(
m
+
1
)
n*(m+1)
n∗(m+1),直接上高斯消元即可。
复杂度:
O
(
n
3
m
3
)
O(n^3m^3)
O(n3m3)。
CODE
#include<bits/stdc++.h>
using namespace std;
#define sf scanf
#define ri register int
#define in red()
#define gc getchar()
#define cs const
#define ll long long
#define db double
inline int red(){
int num=0,f=1;char c=gc;
for(;!isdigit(c);c=gc)if(c=='-')f=-1;
for(;isdigit(c);c=gc)num=(num<<1)+(num<<3)+(c^48);
return num*f;
}
int up,n,m,K,top=0;
inline int id(int x,int y){return (x-1)*(m+1)+y;}
db a[200][200];
inline void gauss(int n){
for(ri i=0;i<n;++i){
int p=i;
for(ri j=i+1;j<=n;++j){
if(fabs(a[j][i])>fabs(a[p][i]))p=j;
}
swap(a[i],a[p]);
if(a[i][i]==0)continue;
for(ri j=0;j<n;++j){
if(j==i)continue;
if(a[j][i]==0)continue;
db k1=a[j][i]/a[i][i];
for(ri k=n;k>=0;--k)a[j][k]-=a[i][k]*k1;
}
}
for(ri i=0;i<n;++i)a[i][i]=a[i][n]/a[i][i];
}
signed main(){
// freopen("data.in","r",stdin);
in;
n=in;m=in;K=in;
up=(m+1)*n;
//end
a[top][id(1,m)]+=1;
a[top][up]+=1;
++top;
for(ri i=2;i<=n;++i)a[top++][id(i,m)]+=1;
//1
for(ri i=0;i<m;++i){
a[top][id(1,i)]+=1;
a[top][id(1,i+1)]+=-0.25;
a[top][id(n-2,1)]+=-0.75;
++top;
a[top][id(2,i)]+=1;
a[top][id(n-1,1)]+=-0.5;
a[top][id(1,1)]+=-0.25;
a[top][id(n-2,i+1)]+=-0.25;
++top;
a[top][id(3,i)]+=1;
a[top][id(n-1,i+1)]+=-0.25;
a[top][id(n-1,1)]+=-0.25;
a[top][id(n,1)]+=-0.25;
a[top][id(1,1)]+=-0.25;
++top;
a[top][id(4,i)]+=1;
a[top][id(n,i+1)]+=-0.25;
a[top][id(n,1)]+=-0.5;
a[top][id(1,1)]+=-0.25;
++top;
}
for(ri i=5;i<=n;++i){
for(ri j=0;j<m;++j){
a[top][id(i,j)]+=1;
a[top][id(i-3,j+1)]+=-0.25;
a[top][id(i-3,1)]+=-0.75;
++top;
}
}
gauss(up);
printf("%.6lf",a[id(K,0)][id(K,0)]);
return 0;
}