题意
B 君很喜欢玩炉石传说天梯模式,但是 B 君很菜。天梯模式规则是这样的。
首先有 25 个等级,最低 25 级,最高 1 级。你需要和别人进行天梯比赛来获得更多的星。
如果你胜利了,你会获得一颗星,如果你失败了,你会失去一颗星。当你当前的星大于一个指定的数目的时候,
你将升入下一等级(即等级减一),并且扣除这个数目的星,这个数目与当前等级有关。
其中 25 到 21 级需要 2 个星升级。20 到 16需要 3 个。15 到 10需要 4 个。10 到 1 需要 5 个。
特别的,如果在 1 级 5 星获胜,你将成为传说。当你当前为 0 星的时候,并且失去一颗星,你会退回到上一等级(即等级加一),并且获得升级所需要的星,然后失去那一颗星。当你当前的状态是 20 级 0 星或更低时,你的失败不会导致星的损失。
当你这局比赛和之前两局比赛均胜利时,且当前的等级不在 1 到 5 级之间时,你可以获得连胜奖励,额外的一颗星,这颗星对升级的影响和一般胜利的星一样。
B君打算从一共 x 星开始玩,B 君每一局的胜率是 p。B 君想知道自己期望上传说需要多少盘天梯比赛。
题意
被题目吸引点进来的
很裸的一个高斯消元啊。。
g[x]=g[赢了的状态]∗p+g[输了的状态]∗(1−p)+1
g
[
x
]
=
g
[
赢
了
的
状
态
]
∗
p
+
g
[
输
了
的
状
态
]
∗
(
1
−
p
)
+
1
高斯消元就可以了。。
但是由于没有小数据不好调。。
搞了很久
一开始方程列错了。。
看来还是要多多练习啊
CODE:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps=1e-7;
const int N=300;
double g[N][N];
int id[N][3];
int n;
double p;
struct qq
{
int x,y,last;
double z;
}e[N];int num,last[N];
int d[N];
void init (int x,int y,double z)
{
num++;d[x]++;
e[num].x=x;e[num].y=y;e[num].z=z;
e[num].last=last[x];
last[x]=num;
}
int cnt;
void Gauss ()
{
for (int u=1;u<=cnt;u++)
{
if (abs(g[u][u])<=eps)
{
for (int i=u;i<=cnt;i++)
{
if (abs(g[i][u])>eps)
{
for (int j=1;j<=cnt+1;j++)
swap(g[u][j],g[i][j]);
break;
}
}
}
for (int i=u+1;i<=cnt;i++)
{
double j=g[i][u]/g[u][u];
for (int l=u;l<=cnt+1;l++)
g[i][l]=g[u][l]*j-g[i][l];
}
}
for (int u=cnt;u>=1;u--)
{
for (int i=u+1;i<=cnt;i++)
g[u][cnt+1]=g[u][cnt+1]-g[u][i]*g[i][cnt+1];
g[u][cnt+1]/=g[u][u];
}
}
int main()
{
num=0;memset(last,-1,sizeof(last));
scanf("%d%lf",&n,&p);
for (int u=0;u<=96;u++)
for (int i=0;i<3;i++)
id[u][i]=++cnt;;
for (int u=1;u<=96;u++)
for (int i=0;i<3;i++)
if (u+i<=96)
{
int k=id[u][i];
if (u>85)//输不掉
g[k][id[u][0]]=1-p;
else
g[k][id[u+1][0]]=1-p;
if (u<=25)//不能连胜
g[k][id[u-1][1]]=p;
else
g[k][id[u-1-(i==2)][i+(i!=2)]]=p;
}
for (int u=1;u<=cnt;u++)
{
g[u][u]-=1;
g[u][cnt+1]=(u>3)?-1:0;
}
Gauss();
printf("%lf\n",g[id[n][0]][cnt+1]);
return 0;
}