51nod 1549 上传说

题目链接 :http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1549

基准时间限制:1 秒 空间限制:131072 KB 分值: 160  难度:6级算法题
 收藏
 关注
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 君想知道自己期望上传说需要多少盘天梯比赛。

Input
第一行第一个整数 n 表示差多少颗星到传说(0 <= n <= 96),第二个实数,表示胜率 p。虽然 B 君很菜,但是因为他是抄卡组,所以保证 0.48 <= p <= 1。
Output
一行一个实数表示答案。
Input示例
96 0.5
Output示例
1384.704397366


岛娘出的题。。。


官方题解:

原问题等价于一共有 95 个星。
每次获胜一局可以得到一个星。
一共需要胜利 96 局。
我们用x[i][j]表示还差i局可以传说,当前连胜 j (0 <= j <= 2)
当 i 大于 85 时不会掉星。
当 i 小于等于 25 时不再有连胜。

然后列一个291元的方程解出来即可。


code:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

const int maxn = 3e2+10;
const double eps = 1e-9;
const double inf = 1<<29;
long double x[maxn][maxn];

int code(int x,int y){
	return x*3+y+1;
}

void display(int n){
	printf("\n-----------------\n");
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n+1;j++) cout<<x[i][j]<<' ';
		cout<<endl;
	}
	printf("-----------------\n\n");
}

int Guass(int n){
//	display(n);
	for(int i=1;i<=n;i++){
		int mr=i;
		for(int k=i;k<=n;k++){
			if(fabs(x[k][i])>fabs(x[mr][i])) mr=k;
		}
		if(mr!=i){
			for(int j=1;j<=n+1;j++) swap(x[i][j],x[mr][j]);
		}
		if(fabs(x[i][i])<eps) return 0;
        for(int j=n+1;j>=i;j--){
            for(int k=i+1;k<n;k++)
                x[k][j]-=x[k][i]/x[i][i]*x[i][j];
        }
	}
	for(int i=n;i>=1;i--){
		for(int j=i+1;j<=n;j++){
            x[i][n+1]-=x[i][j]*x[j][n+1];
        }
        x[i][n+1]/=x[i][i];
	}
//	display(n);
	return 1;
}


int main(){
//    freopen("in.txt","r",stdin);
	int n;
	long double p;
	cin>>n>>p;
    int y = 292;
	memset(x,0,sizeof(x));
	x[code(0,0)][code(0,0)]=1;
	x[code(0,1)][code(0,1)]=1;
	x[code(0,2)][code(0,2)]=1;
	for(int i=1;i<=25;i++){
		for(int j=0;j<=2;j++){
			int c=code(i,j);
			x[c][c]=1;
			x[c][code(i-1,min(j+1,2))]-=p;
			x[c][code(i+1,0)]-=(1-p);
			x[c][y]=1;
		}
	}
	for(int i=26;i<=85;i++){
		for(int j=0;j<=2;j++){
			int c=code(i,j);
			x[c][c]=1;
			x[c][code(i+1,0)]-=(1-p);
			if(j==2) x[c][code(i-2,2)]-=p;
			else x[c][code(i-1,j+1)]-=p;
			x[c][y]=1;
		}
	}
	for(int i=86;i<=96;i++){
		for(int j=0;j<=2;j++){
			int c=code(i,j);
			x[c][c]=1;
			x[c][code(i,0)]-=(1-p);
            if(j==2) x[c][code(i-2,2)]-=p;
            else x[c][code(i-1,j+1)]-=p;
			x[c][y]=1;
		}
	}
	Guass(291);
	long double ans = x[code(n,0)][y];
	printf("%.12Lf\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/oWuHen12/article/details/80198630