您的位置:首页 > 其它

hdu4870 Rating (高斯消元或者dp)

2014-07-23 11:01 288 查看

Rating

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 213 Accepted Submission(s): 126
Special Judge


[align=left]Problem Description[/align]
A little girl loves programming competition very much. Recently, she has found a new kind of programming competition named "TopTopTopCoder". Every user who has registered in "TopTopTopCoder" system will have a rating, and the initial
value of rating equals to zero. After the user participates in the contest held by "TopTopTopCoder", her/his rating will be updated depending on her/his rank. Supposing that her/his current rating is X, if her/his rank is between on 1-200 after contest, her/his
rating will be min(X+50,1000). Her/His rating will be max(X-100,0) otherwise. To reach 1000 points as soon as possible, this little girl registered two accounts. She uses the account with less rating in each contest. The possibility of her rank between on
1 - 200 is P for every contest. Can you tell her how many contests she needs to participate in to make one of her account ratings reach 1000 points?

[align=left]Input[/align]
There are several test cases. Each test case is a single line containing a float number P (0.3 <= P <= 1.0). The meaning of P is described above.

[align=left]Output[/align]
You should output a float number for each test case, indicating the expected count of contest she needs to participate in. This problem is special judged. The relative error less than 1e-5 will be accepted.

[align=left]Sample Input[/align]

1.000000
0.814700

[align=left]Sample Output[/align]

39.000000
82.181160

一场比赛,赢了可以得50分,输了扣100分,分数会超过1000和不会小于0.有个人用2个账号,始终用分数低的号比赛。已知赢一场比赛的概率为p求打到1000分的场数的期望值。

1、可以用高斯消元,

令E(X,Y)为账号分数为x,y打到1000的数学期望。则有:

E(X,Y)=PE(X1,Y1)+(1-P)E(X2,Y2)+1,X1,Y1是XY分数赢了的分数,X2,Y2对应是输了的分数,假设X>=Y,每次比赛用Y的账号,就会有210条方程,用mark数组标记XY分数对应的系数的索引。

代码:

#include <iostream>
#include <cmath>
#include <stdio.h>
#include <algorithm>
#include <ctime>
#include <vector>
#include <cstring>
#include <map>
#include <string>
#include <queue>
using namespace std;
#define LL long long
#define ULL unsigned long long
//#define REP(i,n) for(int i=0;i<n;++i)
#define REP(i,a,b) for(int i=a;i<=b;++i)
#define INFLL (1LL)<<62
#define mset(a) memset(a,0,sizeof a)
#define FR(a) freopen(a,"r",stdin)
#define FW(a) freopen(a,"w",stdout)
#define PI 3.141592654
const LL MOD = 1000000007;
const int maxn=222;
const double eps=1e-9;
double a[maxn][maxn];
int mark[25][25];
int cnt;
double gauss()
{
int m=211;
int n=210;
for(int i=0;i<n;i++)
{
int k=i;
for(;k<n;++k)
if(fabs(a[k][i])>eps)    break;
if(i!=k)
for(int j=0;j<=n;++j)
swap(a[i][j],a[k][j]);
for(int j=0;j<n;++j)
{
if(i==j)    continue;
if(fabs(a[j][i])<eps)    continue;
double x=a[j][i]/a[i][i];
for(k=i;k<m;++k)
a[j][k]-=a[i][k]*x;
}
}
return a[0]
/a[0][0];
}

void makeMat(double p)
{
mset(a);
int m=211;
int x=0,y=0;
for(y=0;y<20;++y){
for(x=0;x<y;++x)
{
int temp=mark[y][x];
a[temp][temp]=1;
a[temp][m-1]=1;
int temp2=mark[y][max(0,x-2)];
a[temp][temp2]-=1-p;
temp2=mark[y][x+1];
a[temp][temp2]-=p;
}
int t=mark[y][y];
a[t][t]=1;
a[t][m-1]=1;
int tt=mark[y][max(0,x-2)];
a[t][tt]-=1-p;
tt=mark[x+1][x];
a[t][tt]-=p;
}
}

int main()
{
double p;
cnt=0;
mset(mark);
REP(i,0,20)
REP(j,0,i)
mark[i][j]=cnt++;
while (cin>>p)
{
makeMat(p);
printf("%.6lf\n",gauss());
}
}


2、用dp

首先离散化,因为每场比赛分数的变化都是50的倍数,令每场赢了得1分,输了扣2分。

dp[i]表示单场比赛从i分数提高到i+1的分数的期望值,

则有:dp[i]=p+(1-p)(dp[i-2]+dp[i-1]+dp[i]+1)  

 ==>dp[i]=1/p+(1-p)/p*(dp[i-2]+dp[i-1]);dp[0]=1/p,dp[1]=1/p/p;

用ans[i][i]表示两个账号分数从0打到ii的期望,对于账号分数的上升,他们是交错上升的,意思是当他们分数一样的时候,前面的赢一分,当前面的赢了一分之后,下一场就后面的赢,所以只需要维护ans[i+1][i] 和ans[i+1][i+1],且

ans[i+1][i]=ans[i][i]+dp[i],ans[i+1][i+1]=ans[i+1][i]+dp[i],

代码:

#include <iostream>
#include <cmath>
#include <stdio.h>
using namespace std;
double dp[22];
double ans[22][22];

int main()
{
double p;
while (cin>>p)
{
dp[0]=1/p;
dp[1]=1/p/p;
for(int i=2;i<20;++i)
dp[i] = 1+(1-p)/p*(dp[i-2]+dp[i-1]+1);
ans[0][0]=0;
for (int i=0;i<20;++i)
{
ans[i+1][i]=ans[i][i]+dp[i];
ans[i+1][i+1]=ans[i+1][i]+dp[i];
}
printf("%.6lf\n",ans[20][19]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: