LightOJ - 1151概率dp+高斯消元
概率dp+高斯消元
https://vjudge.net/problem/LightOJ-1151
题意:刚开始在1,要走到100,每次走的距离1-6,超过100重来,有一些点可能有传送点,可以传送到前面或后面,那么概率dp没法递推,只能高斯消元
设期望E(x),首先100这个位置的期望E(100)=0,然后可以找出方程, 对于传送点,E(x)=E(go(x)),对于非传送点,E(x)=(E(x+1)+E(x+2)+E(x+3)+E(x+4)+E(x+5)+E(x+6)+6)/cnt(cnt是可转移的点数)
对于大于100的E肯定是0,不用考虑进来,然后高斯消元就得到了结果
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-8; const int N=100+10,maxn=100000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; double a[N][N],ans[N]; void gauss(int n) { for(int i=1;i<n;i++) { if(a[i][i]==0) { int id=0; for(int j=i+1;j<=n;j++) if(a[j][i]!=0) id=j; for(int j=i;j<=n+1;j++) swap(a[i][j],a[id][j]); } for(int j=i+1;j<=n;j++) { double t=a[j][i]/a[i][i]; for(int k=i;k<=n+1;k++) a[j][k]-=(a[i][k]*t); } } // for(int i=1;i<=n;i++) // { // for(int j=1;j<=n+1;j++) // printf("%.12f ",a[i][j]); // puts(""); // } for(int i=n;i>=1;i--) { for(int j=i+1;j<=n;j++) a[i][n+1]-=ans[j]*a[i][j]; ans[i]=a[i][n+1]/a[i][i]; } } int go[N]; int main() { int T,cnt=0;scanf("%d",&T); while(T--) { int n;scanf("%d",&n); memset(go,0,sizeof go); for(int i=0;i<n;i++) { int a,b; scanf("%d%d",&a,&b); go[a]=b; } // puts("++"); memset(a,0,sizeof a); for(int i=1;i<=93;i++) { if(go[i]) { a[i][i]=1; a[i][go[i]]=-1; } else { a[i][i]=6.0; for(int j=i+1;j<=i+6;j++)a[i][j]=-1.0; a[i][101]=6; } } for(int i=94;i<=99;i++) { if(go[i]) { a[i][i]=1; a[i][go[i]]=-1; } else { a[i][i]=1.0*(100-i); for(int j=i+1;j<=100;j++)a[i][j]=-1.0; a[i][101]=6; } } a[100][100]=1.0; gauss(100); printf("Case %d: %.12f\n",++cnt,ans[1]); } return 0; } /*********************** ***********************/