2014 Multi-University Training Contest 1 - J Rating

时间:2022-03-02 04:35:53

题目链接: 

pid=4870">http://acm.hdu.edu.cn/showproblem.php?pid=4870

题目大意:

题意:一个人注冊两个账号,初始rating都是0,他每次拿低分的那个号去打比赛,赢了加50分,输了扣100分,胜率为p,他会打到直到一个号有1000分为止,问比赛场次的期望。

解题思路:

用E(x。y)表示到(1000, 950)这个状态须要多少场。由于(1000,X) X != 950 这样的情况是不可能发生的。最后E(0,0)就是答案。

E(x1, y1) = E(x2, y2) * p + E(x3, y3) * (1 - p) + 1 是状态,所以能够列出210个方程。用高斯消元就可以。

代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<deque>
#include<list>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<numeric>
#include<iomanip>
#include<bitset>
#include<sstream>
#include<fstream>
#define debug puts("-----")
#define pi (acos(-1.0))
#define eps (1e-8)
#define inf (1<<30)
#define seek 31
#define LL long long
#define ULL unsigned long long
#define maxn 222
#define For(i, n) for (int i = 0; i < n; i++)
using namespace std;
double a[maxn][maxn] = {0}, ans[maxn] = {0};
bool l[maxn];
int n;
inline int solve(double a[][maxn], bool l[], double ans[], const int& n) {
int res = 0, r = 0;
for (int i = 0; i < n; i++) l[i] = false;
for (int i = 0; i < n; i++) {
for (int j = r; j < n; j++)
if (fabs(a[j][i]) > eps) {
for (int k = i; k <= n; k++) swap(a[j][k], a[r][k]);
break;
}
if (fabs(a[r][i]) < eps) {
res++;
continue;
}
for (int j = 0; j < n; j++)
if (j != r && fabs(a[j][i]) > eps) {
double tmp = a[j][i] / a[r][i];
for (int k = i; k <= n; k++) a[j][k] -= tmp * a[r][k];
}
l[i] = true, r++;
}
for (int i = 0; i < n; i++)
if (l[i])
for (int j = 0; j < n; j++)
if (fabs(a[j][i]) > 0)
ans[i] = a[j][n] / a[j][i];
return res;
} int cnt = 0, mark[22][22] = {0};
double p;
void build() {
for (int i = 0; i < 20; i++) {
for (int j = 0; j <= i; j++) {
int x = mark[i][j];
a[x][x] = 1, a[x][210] = 1;
a[x][mark[i][max(0, j - 2)]] -= (1 - p);
a[x][mark[max(i, j + 1)][min(i, j + 1)]] -= p;
}
}
}
int main () {
memset(mark, -1, sizeof(mark));
for (int i = 0; i < 20; i++)
for (int j = 0; j <= i; j++)
mark[i][j] = cnt++;
while(~scanf("%lf", &p)) {
memset(a, 0, sizeof(a));
build();
solve(a, l, ans, 210);
printf("%.6lf\n", ans[0]);
}
return 0;
}