概率dp(求期望)+高斯消元 hdu-4418-Time travel
来源:互联网 发布:c语言书籍推荐 编辑:程序博客网 时间:2024/05/17 06:35
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4418
题目大意:
有n个点标号为0~n-1,A从x点出发每次可以走1~m步,走k步的概率为pk, 如果到达了n-1点,则往回走即(n-1~0),求走到y时走的步数的概率。
解题思路:
概率dp+高斯消元。
因为0~n-1中的点都有方向,为了是方向统一,可以增加n-2个点,使统一向一个方向走0~n-1~0
n-1右边的点表示向左走,两种不同的状态。
dp[i]表示从i开始到达终点的步数期望 dp[i]=(dp[i+1]+1)*p1+(dp[i+2]+2)*p2+(dp[i+3]+3)*p3.......。
注意有些点不能到达,所以先BFS找能够到达的点,对于不能到达的点直接输出Impossible
然后构建2*n-2元方程求解就行了。注意有些步数不能走。
最好把能够有效的状态单独拿出来,直接重新构建方程。
代码:
#include<iostream>#include<cmath>#include<cstdio>#include<cstdlib>#include<string>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#define eps 1e-6#define INF 0x1f1f1f1f#define PI acos(-1.0)#define ll __int64#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;//freopen("data.in","r",stdin);//freopen("data.out","w",stdout);#define Maxn 210int gap[Maxn],cnt,nn;int vis[Maxn],n,m,x,y,d;double pp[Maxn];double g[Maxn][Maxn],xx[Maxn];void bfs(){ queue<int>myq; myq.push(x); vis[x]=true; while(!myq.empty()) { int tmp=myq.front(); myq.pop(); if(tmp==y||tmp==nn-y) //到了终点后就不能再走了 continue; for(int i=1;i<=cnt;i++) { int tt; tt=(tmp+gap[i])%nn; //统一转化成向一个方向走 if(vis[tt]) continue; vis[tt]=true; myq.push(tt); } }}void gg(int row,int col) //高斯消元 0~row 和0~col{ for(int i=0,j=0;i<row,j<col;i++,j++) { int t=i; for(int k=i+1;k<=row;k++) if(fabs(g[k][j])>fabs(g[t][j])) t=k; if(fabs(g[t][j])<eps) continue; if(t-i) { for(int k=i;k<=col;k++) swap(g[i][k],g[t][k]); } for(int q=i+1;q<=row;q++) { if(fabs(g[q][j])<eps) //该系数已经变成了0 continue; double tmp=g[q][j]/g[i][j]; g[q][j]=0.0; for(int k=j+1;k<=col;k++) g[q][k]-=tmp*g[i][k]; } } for(int i=row;i>=0;i--) { if(fabs(g[i][i])<eps) //系数都为0了 continue; xx[i]=g[i][col]; for(int j=row;j>i;j--) xx[i]-=g[i][j]*xx[j]; xx[i]/=g[i][i]; }}int main(){ int t,a; scanf("%d",&t); while(t--) { scanf("%d%d%d%d%d",&n,&m,&y,&x,&d); cnt=0; double sum=0.0; for(int i=1;i<=m;i++) { scanf("%d",&a); if(a) //可走 { gap[++cnt]=i; //能走的 pp[cnt]=a*1.0/100.0; sum+=pp[cnt]*i; } } //cout<<sum<<endl; if(x==y) //起点和终点为同一点 { printf("0.00\n"); continue; } memset(vis,false,sizeof(vis)); nn=2*n-2; if(d>0) x=nn-x; //两种不同的状态 bfs(); if(!vis[y]&&!vis[2*n-2-y]) //不能到达 { printf("Impossible !\n"); continue; } memset(g,0,sizeof(g)); for(int i=0;i<nn;i++) //枚举开始的位置,注意一共有nn个未知数 { if(!vis[i]) continue; //把不能到达的都清零,无效方程,没关系 g[i][i]+=1.0; if(i==y||i==nn-y) continue; for(int j=1;j<=cnt;j++) { int tt=(i+gap[j])%nn; g[i][tt]-=pp[j]; } g[i][nn]+=sum; } gg(nn-1,nn); printf("%0.2f\n",xx[x]); } return 0;}
- 概率dp(求期望)+高斯消元 hdu-4418-Time travel
- HDU 4418 Time travel 概率DP 高斯消元
- HDU 4418Time travel 概率dp+高斯消元
- Hdu 4418 Time travel 概率DP
- HDU 4418 Time travel(高斯消元+概率DP)
- HDU 4418 Time travel (概率DP+高斯消元)
- HDU 4418 Time travel (概率,高斯消元)
- hdu-4418-Time travel-高斯+概率dp
- hdu 4418 Time travel (概率dp 细节好多)
- HDU 4118 Time travel (高斯消元+概率dp)
- [ACM] hdu 4418 Time travel (高斯消元求期望)
- 【HDU 4418】【概率DP 高斯消元】 Time travel 给出一个数轴,有一个起点和终点,某人可以走1-m步,每一种有一个概率,初始有一个方向,走到头则返回,问到达终点期望
- hdu4418 Time travel 【期望+dp】
- HDU 4418 Time travel 概率 高斯
- hdu 4405 概率dp 求期望
- hdu 4035概率dp 求期望
- hdu 4035 概率,求期望dp
- hdu 4035 经典概率dp求期望
- hdu 4681 string
- C#日期国家区域指定
- android自动化测试工具简介
- openssl 相关的rsa与sha1算法签名与验证
- Ubuntu12.10环境下载Android源代码
- 概率dp(求期望)+高斯消元 hdu-4418-Time travel
- Android---画廊(Gallery)
- try-catch-finally与资源关闭
- [译]SSO解决方案大全 Single Sign-On for everyone
- QT QTableView用法小结
- at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
- 分布式拒绝服务攻击(DDoS)原理及防范
- 解决IE7下z-index 无效的问题
- 系统初始化函数集(subsys_initcall)和初始化段应用