hdu4418 Time travel(高斯消元法+概率)
2015-09-22 18:59
246 查看
题目链接:点击打开链接
题意描述:给定一个坐标轴范围0~n-1,一个人从坐标x出发每次可以走1~m步(每步的概率不同,总的概率和为1)走到坐标y,初始时向左或向右,每次走到端点后会折返走回来
问从x出发平均走多远能够到达y?
解题思路:高斯消元法+概率
分析:(巧妙之处:将向左和向右两种状态通过0~n-1、n-2~1这样的拼接方式全部转换为向右,同时%(2*(n-1)))
1、由于有0~n-1个位置,除了端点外每个位置有向左或向右的方向,所以一共有2*(n-1)中状态,转化到线性方程组中即有2*(n-1)个未知数
2、首先我们进行bfs判断从x是否能走到y,同时为每一个位置编一个状态编号,便于写出线性方程组
3、从每一个状态出发,对1~m的所有情况进行计算,建立线性方程组(当前平均步数E(u) - 所有可能的情况P[v]*E[v] = P[v]*(v-u))
4、使用高斯消元法求解线性方程组即可
代码:
题意描述:给定一个坐标轴范围0~n-1,一个人从坐标x出发每次可以走1~m步(每步的概率不同,总的概率和为1)走到坐标y,初始时向左或向右,每次走到端点后会折返走回来
问从x出发平均走多远能够到达y?
解题思路:高斯消元法+概率
分析:(巧妙之处:将向左和向右两种状态通过0~n-1、n-2~1这样的拼接方式全部转换为向右,同时%(2*(n-1)))
1、由于有0~n-1个位置,除了端点外每个位置有向左或向右的方向,所以一共有2*(n-1)中状态,转化到线性方程组中即有2*(n-1)个未知数
2、首先我们进行bfs判断从x是否能走到y,同时为每一个位置编一个状态编号,便于写出线性方程组
3、从每一个状态出发,对1~m的所有情况进行计算,建立线性方程组(当前平均步数E(u) - 所有可能的情况P[v]*E[v] = P[v]*(v-u))
4、使用高斯消元法求解线性方程组即可
代码:
#include <cstdio> #include <cstring> #include <cmath> #include <queue> #define eps 1e-8 #define MAXN 210 #define mem(a,b) memset(a,b,sizeof(a)) #define zero(a) fabs(a)<eps using namespace std; typedef vector<double> vec; typedef vector<vec> mat; int n,m,y,x,d; int s,cnt,id[MAXN],g[MAXN]; double p[MAXN],a[MAXN][MAXN]; bool bfs(){ queue<int> q; q.push(s); cnt=0;mem(id,-1); id[s]=cnt++;///对每一个可行的位置进行状态编号 bool flag=false; while(!q.empty()){ int u=q.front();q.pop(); for(int i=1;i<=m;++i){ int v=(u+i)%(2*n-2); if(zero(p[i])) continue; if(id[v]!=-1) continue; id[v]=cnt++;///保存每个位置对应的状态编号 if(g[v]==y){flag=true;} q.push(v); } } return flag; } void Build(){///构造多项式 mem(a,0); for(int i=0;i<(2*n-2);++i){ if(id[i]==-1) continue; int u=id[i]; a[u][u]=1; if(g[i]==y){a[u][cnt]=0;continue;} for(int j=1;j<=m;++j){ int v=(i+j)%(2*n-2); if(id[v]==-1) continue; v=id[v]; a[u][v]-=p[j];///从E(u)-p[j]=sum<p[j]*j> a[u][cnt]+=p[j]*j; } } } bool gauss(int nn){///高斯消元 int i,j; for(i=0,j=0;i<nn&&j<nn;++j){ int k; for(k=i;k<nn;++k) if(!zero(a[k][j])) break; if(k<nn){ if(i!=k) for(int r=j;r<=nn;++r) swap(a[i][r],a[k][r]); double tt=1/a[i][j]; for(int r=j;r<=nn;r++) a[i][r]*=tt; for(int r=0;r<nn;++r) if(r!=i){ for(int t=nn;t>=j;t--) a[r][t]-=a[r][j]*a[i][t]; } ++i; } } for(int r=i;r<nn;++r){ if(!zero(a[r] )) return false; } return true; } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d%d%d%d%d",&n,&m,&y,&x,&d); for(int i=1;i<=m;++i){ scanf("%lf",&p[i]);p[i]/=100.0; } if(y==x){ puts("0.00"); continue; }///特判,能直接判断尽量直接判断(防止RE) if(d==0||d==-1) s=x; else if(d==1) s=n+(n-2-x); for(int i=0;i<n;++i) g[i]=i; for(int i=n,j=n-2;j>=1;j--,i++) g[i]=j; if(!bfs()){ puts("Impossible !"); continue; } Build(); if(!gauss(cnt)) puts("Impossible !"); else{ double ans=a[id[s]][cnt]; if(zero(ans)) printf("0.00\n");///精度问题,注意卡精度 else printf("%.2lf\n",ans); } } return 0; }
相关文章推荐
- IOS UIView
- Single Number
- python3 入门 (一) 基础语法
- ThinkPHP-给已上传图片生成缩略图并在列表显示
- HDU_3376_Matrix Again(最小费用流)
- Cookie
- android的消息处理机制(图文+源码分析)—Looper/Handler/Message[转]
- bounds的剖析
- Notification的使用(待完善)-〉添加点击取消,显示优化
- 0,22, 47, 120,(? ),290
- 火星信息安全研究院
- ./configure是干什么的?make install又是干什么的?
- hdu1166解题报告
- VirtualBox中开启Linux的SSH(CentOS)
- C++编写四则运算生成程序
- 堆栈
- $.ajax()方法详解
- 在JAVA中封装JSONUtils工具类及使用
- design pattern scard
- 不容忽视的网络安全