HDU 4418 Time travel(高斯消元+概率DP)
2015-09-15 20:34
239 查看
题意:一个人在数轴上来回走,以pi的概率走i步i∈[1, m],给定n(数轴长度),m,e(终点),s(起点),d(方向),求从s走到e经过的点数期望。
思路:先把n(n>1)个点展开成2*n-2个点,这一步的作用是简化方向这个状态,使得现在所有点在一条直线上,例如原来是01234321,现在展开成了01234567.
设dp[i]为当前在i点走到目标点的期望步数,根据状态转移可以得到若干方程
但是,这些方程里有些是不合法的,所以会导致结果错误,
这是因为,对于一个点来说,可能从起点走不到这个点,但是方程组里我们还是保留了这些方程,这样的话结果计算出来就会错误,所以在开始时我们可以一次bfs将所有能到达的点标记并重新编号,然后计算这些点的状态转移方程。
题意:一个人在数轴上来回走,以pi的概率走i步i∈[1, m],给定n(数轴长度),m,e(终点),s(起点),d(方向),求从s走到e经过的点数期望。
思路:先把n(n>1)个点展开成2*n-2个点,这一步的作用是简化方向这个状态,使得现在所有点在一条直线上,例如原来是01234321,现在展开成了01234567.
设dp[i]为当前在i点走到目标点的期望步数,根据状态转移可以得到若干方程
但是,这些方程里有些是不合法的,所以会导致结果错误,
这是因为,对于一个点来说,可能从起点走不到这个点,但是方程组里我们还是保留了这些方程,这样的话结果计算出来就会错误,所以在开始时我们可以一次bfs将所有能到达的点标记并重新编号,然后计算这些点的状态转移方程。
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<map> #include<set> #include<ctime> #define eps 1e-9 #define LL long long #define pii pair<int, int> //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; int n, m, Y, X, d; const int MAXN=220; double p[MAXN]; double a[MAXN][MAXN],x[MAXN];//方程的左边的矩阵和等式右边的值,求解之后x存的就是结果,行列编号从0开始 int equ,var;//方程数和未知数个数 int num[MAXN]; int Gauss() { int i,j,k,col,max_r; for(k=0,col=0;k<equ&&col<var;k++,col++) { max_r=k; for(i=k+1;i<equ;i++) if(fabs(a[i][col])>fabs(a[max_r][col])) max_r=i; if(fabs(a[max_r][col])<eps)return 0; if(k!=max_r) { for(j=col;j<var;j++) swap(a[k][j],a[max_r][j]); swap(x[k],x[max_r]); } x[k]/=a[k][col]; for(j=col+1;j<var;j++)a[k][j]/=a[k][col]; a[k][col]=1; for(i=0;i<equ;i++) if(i!=k) { x[i]-=x[k]*a[i][k]; for(j=col+1;j<var;j++)a[i][j]-=a[k][j]*a[i][col]; a[i][col]=0; } } return 1; } int bfs() { queue<int> q; q.push(X); int cnt = 0; memset(num, -1, sizeof(num)); num[X] = cnt++; while(!q.empty()) { int t = q.front(); q.pop(); for(int i = 1; i <= m; i++) { if(fabs(p[i]) < eps) continue; int id = (t+i)%n; if(num[id] == -1) { num[id] = cnt++; q.push(id); } } } return cnt; } int main() { //freopen("input.txt", "r", stdin); int T; cin >> T; while(T--) { int tmp; scanf("%d%d%d%d%d", &tmp, &m, &Y, &X, &d); for(int i = 1; i <= m; i++) scanf("%lf", &p[i]), p[i]/=100; n = 2*tmp - 2; if(!n) n+=1; if(d>0) X = n - X; equ = var = bfs(); if(num[Y]==-1 && num[n-Y]==-1) { printf("Impossible !\n"); continue; } memset(x, 0, sizeof(x)); memset(a, 0, sizeof(a)); for(int i = 0; i < n; i++) { if(num[i]==-1) continue; a[num[i]][num[i]] = 1.0; if(i==Y || i==n-Y) continue; for(int j = 1; j <= m; j++) { int id = (i+j) % n; if(num[id] != -1) { a[num[i]][num[id]] -= p[j]; x[num[i]] += j*p[j]; } } } if(Gauss()) printf("%.2f\n", x[num[X]]); else printf("Impossible !\n"); } return 0; }
相关文章推荐
- TCP/IP 协议的工作流程
- 一种随机处理方法
- Android 学习第16课,java 包、类等相关的一些基础知识
- git shell 常用命令
- poj1068
- SVN版本冲突中 Files 的值“ < < < < < < < .mine”无效路径中具有非法字符的解决办法:
- HDU 1025 Constructing Roads In JGShining's Kingdom
- list-each-while遍历数组
- BZOJ 1130 [POI2008]POD Subdivision of Kingdom 状压
- 学习Spring必学的Java基础知识
- HDU 5446——Unknown Treasure——————【CRT+lucas+exgcd+快速乘+递推求逆元】
- loadView、viewDidLoad及viewDidUnload的关系
- Android之ViewPager使用(用美女做的背景,给你疲惫的眼睛视觉冲击)
- 杀人游戏
- ZOJ 1729 & ZOJ 2006(最小表示法模板题)
- iOS:删除storyBoard,纯代码实现UITabBarController的视图切换功能
- RazorHelper.cs
- grep记录
- android 图片裁剪,显示 指定压缩
- 安卓中回调实现Fragment向Activity传值