lightoj1151
题意:
- 有100个格子,从1开始走,每次随机走1~6。有n个格子会单向传送到其他格子,tp[i]表示从i传送到tp[i]。
- 1和100不会有传送,一个格子也不会有两种传送。问走到100投色子的期望值,注意不能走到100以外。
题解
- dp[i]表示从i到100的还需要的期望次数
- 如果有传送门,那么dp[i] = dp[v[i]]
- 如果没有传送门:dp[i] = 1/6 * ∑(dp[i+j] + 1)(j from 1 to k) + 1/6 * ∑(dp[i] + 1)(j from k+1 to 6),其中k = min(100-i,6);
- 化简得到:k * dp[i] - ∑dp[i+j] = 6 (j from 1 to k)
- 联立方程组
- k * dp[i] - ∑dp[i+j] = 6 (j from 1 to k)
- dp[i] = dp[v[i]]
- 高斯消元求解dp[1]
代码
#include <bits/stdc++.h>
using namespace std;
int const N = 100 + 10;
int n,v[N];
double a[N][N];
void SwapRow(double a[][N],int n,int p,int q){
for(int i=p;i<=n+1;i++)
swap(a[p][i],a[q][i]);
}
void SelectColE(double a[][N],int n){
for(int i=1;i<=n-1;i++){
int MaxRowE = i;
for(int j=i;j<=n;j++)
if(fabs(a[j][i]) > fabs(a[MaxRowE][i])) MaxRowE = j;
if(i != MaxRowE) SwapRow(a,n,i,MaxRowE);
for(int j=i+1;j<=n;j++){
double temp = a[j][i] / a[i][i];
for(int k=i;k<=n+1;k++)
a[j][k] -= a[i][k] * temp;
}
}
}
void Back_Substitution(double a[][N],int n){
for(int i=n;i>=1;i--)
{
for(int j=i+1;j<=n;j++)
a[i][n+1] -=a[i][j] * a[j][n+1];
a[i][n+1] /=a[i][i];
}
}
void Gauss_Elimination(double a[][N],int n){
SelectColE(a,n);
Back_Substitution(a,n);
}
int main(){
int T,caser = 0;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++){
int x,y;
scanf("%d%d",&x,&y);
v[x] = y;
}
memset(a,0,sizeof(a));
a[100][100] = 1; //表示E[100] = 0;所有加上系数 初始化
for(int i=1;i<100;i++){
if(v[i]){ //如果发生跳转
a[i][i] = 1;
a[i][v[i]] = -1;
}else{ //如果不跳转
int k = min(6,100 - i);
a[i][i] = k;
for(int j=1;j<=k;j++)
a[i][i+j] = -1;
a[i][101] = 6;
}
}
Gauss_Elimination(a,100);
printf("Case %d: %.6lf\n",++caser,a[1][101]);
}
return 0;
}