题目链接

BZOJ4418

题解

题意:从一个序列上某一点开始沿一个方向走,走到头返回,每次走的步长各有概率,问走到一点的期望步数,或者无解

我们先将序列倍长形成循环序列,\(n = (N - 1) \times 2\)

按期望\(dp\)的套路,我们设\(f[i]\)为从\(i\)点出发到达终点的期望步数【一定要这么做,不然转移方程很难处理】,显然终点\(f[Y] = f[(n - Y) \mod n] = 0\)

剩余的点

\[f[i] = \sum\limits_{j = 1}^{M} p_j(f[(i + j) \mod n] + j)
\]

这是一个有后效性的转移方程,高斯消元即可

但还没完,有时候有些点是无法到达的,比如每次\(100 \%\)走两步时,恰好\(n\)又是奇数

这个时候这些点无解,但不代表终点无解

我们只需\(bfs\)一遍,强行将无法到达的点设为\(INF\)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
#define res register
#define eps 1e-9
using namespace std;
const int maxn = 205,maxm = 100005;
const double INF = 100000000000000000ll;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
double A[maxn][maxn],p[maxn],ans[maxn];
int n,N,M,Y,X,D,vis[maxn];
int q[maxn],head,tail;
bool bfs(){
for (res int i = 0; i < n; i++) vis[i] = false;
vis[X] = true; q[head = tail = 0] = X;
int u;
while (head <= tail){
u = q[head++];
for (res int i = 1; i <= M; i++)
if (p[i] > eps){
int to = ((u + i) % n + n) % n;
if (!vis[to]) vis[to] = true,q[++tail] = to;
}
}
for (int i = 0; i < n; i++) if (!vis[i]){
A[i][n] = INF,A[i][i] = 1;
}
return vis[Y] || vis[(n - Y) % n];
}
void pre(){
for (int i = 0; i < n; i++)
if (vis[i]){
A[i][i] = 1;
if (i == Y || i == (n - Y) % n) continue;
for (int j = 1; j <= M; j++){
int u = ((i + j) % n + n) % n;
A[i][u] += -p[j];
A[i][n] += p[j] * j;
}
}
}
bool gause(){
for (res int i = 0; i < n; i++){
int j = i;
for (res int k = i + 1; k < n; k++)
if (fabs(A[k][i]) > fabs(A[j][i])) j = k;
if (j != i) for (int k = i; k <= n; k++) swap(A[i][k],A[j][k]);
if (fabs(A[i][i]) < eps) return false;
for (res int j = i + 1; j < n; j++){
double t = A[j][i] / A[i][i];
for (res int k = i; k <= n; k++)
A[j][k] -= A[i][k] * t;
}
}
for (res int i = n - 1; ~i; i--){
for (res int j = i + 1; j < n; j++)
A[i][n] -= A[i][j] * ans[j];
if (fabs(A[i][i]) < eps) return false;
ans[i] = A[i][n] / A[i][i];
}
return true;
}
int main(){
int T = read();
while (T--){
N = read(); M = read(); Y = read(); X = read(); D = read();
n = 2 * (N - 1);
if (D == -1){
if (X == 0) D = 0;
else D = 1;
}
if (D >= 1) X = (n - X) % n;
for (int i = 1; i <= M; i++)
p[i] = read() / 100.0;
if (X == Y){puts("0.00"); continue;}
for (res int i = 0; i < n; i++)
for (res int j = 0; j <= n; j++)
A[i][j] = 0;
if (!bfs()) {puts("Impossible !"); continue;}
pre();
if (!gause() || ans[X] >= INF)
puts("Impossible !");
else printf("%.2lf\n",ans[X]);
}
return 0;
}

最新文章

  1. js删除数组指定元素
  2. javase-排序
  3. mysql实验
  4. HC蓝牙模块测试AT指令搭建外部电路遇到的问题
  5. Git哲学与使用
  6. NOIP2003 加分二叉树
  7. 通过string型类名实例化一个类
  8. 漫游Kafka设计篇之性能优化
  9. asp web api 怎么使用put和delete。
  10. CDN原理
  11. 利用反射生成SQL语句
  12. Oracle11g R2学习系列 之十 解决EM不能用
  13. Delphi启动/停止Windows服务,启动类型修改为&quot;自动&quot;
  14. 从web图片裁剪出发:了解H5中的Blob
  15. Java——多态浅析
  16. SQL Server代码段
  17. Windows下用PIP安装scipy出现no lapack/blas resources found
  18. maven小结
  19. 给recycleview加headview
  20. rabbitmq heartbeat missing with heartbeat = N seconds原因总结

热门文章

  1. PyCharm+QT Designer整合
  2. scala成长之路(1)基本语法和数据类型
  3. python中如何统计一个类的实例化对象
  4. Java学习笔记二:Java开发工具Eclipse的安装与使用
  5. python入门——Anaconda安装
  6. fiddler手机抓包配置方法
  7. 4-oracle11g安装
  8. mac 安装php redis扩展
  9. How to find your web part
  10. 【赛后补题】(HDU6223) Infinite Fraction Path {2017-ACM/ICPC Shenyang Onsite}