题目链接

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;
}

hdu4418 Time travel 【期望dp + 高斯消元】的更多相关文章

  1. HDU4418 Time travel(期望dp 高斯消元)

    题意 题目链接 Sol mdzz这题真的太恶心了.. 首先不难看出这就是个高斯消元解方程的板子题 \(f[x] = \sum_{i = 1}^n f[to(x + i)] * p[i] + ave\) ...

  2. HDU-4418 Time travel 概率DP,高斯消元

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4418 题意:简单来说就是给你1个环(n - 1 , n - 2 …… 0 ,1 , 2 , 3 …… ...

  3. BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元

    BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元 题意: 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机 ...

  4. 期望dp+高斯消元+bfs——hdu4418

    高斯消元又弄了半天.. 注意只要能建立矩阵,那就必定有解,所以高斯消元里可以直接return 1 #include<bits/stdc++.h> using namespace std; ...

  5. HDU 2262 Where is the canteen 期望dp+高斯消元

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2262 Where is the canteen Time Limit: 10000/5000 MS ...

  6. 【noi2019集训题1】 脑部进食 期望dp+高斯消元

    题目大意:有n个点,m条有向边,每条边上有一个小写字母. 有一个人从1号点开始在这个图上随机游走,游走过程中他会按顺序记录下走过的边上的字符. 如果在某个时刻,他记录下的字符串中,存在一个子序列和S2 ...

  7. LightOJ 1151 Snakes and Ladders 期望dp+高斯消元

    题目传送门 题目大意:10*10的地图,不过可以直接看成1*100的,从1出发,要到达100,每次走的步数用一个大小为6的骰子决定.地图上有很多个通道 A可以直接到B,不过A和B大小不确定   而且 ...

  8. P4457-[BJOI2018]治疗之雨【期望dp,高斯消元】

    正题 题目链接:https://www.luogu.com.cn/problem/P4457 题目大意 开始一个人最大生命值为\(n\),剩余\(hp\)点生命,然后每个时刻如果生命值没有满那么有\( ...

  9. ZJUT 1423 地下迷宫(期望DP&高斯消元)

    地下迷宫 Time Limit:1000MS  Memory Limit:32768K Description: 由于山体滑坡,DK被困在了地下蜘蛛王国迷宫.为了抢在DH之前来到TFT,DK必须尽快走 ...

随机推荐

  1. Lavavel5.5源代码 - 并发数控制

    app('redis')->connection('default')->funnel('key000') // 每个资源最大锁定10秒自动过期,只有60个资源(并发),在3秒内获取不到锁 ...

  2. 20180803UnionPay银联支付

    LNMP环境下开发的银联支付(测试环境) 1.准备条件 a.银联支持API:https://open.unionpay.com/ajweb/help/api b.选择开发软件包 图示: c.我选择: ...

  3. 九、IIC驱动原理分析

    学习目标:学习IIC驱动原理: 一.IIC总线协议 IIC串行总线包括一条数据线(SDA)和一条时钟线(SCL),支持“一主多从”和“多主机”模式:每个从机设备都有唯一的地址来识别. 图 1 IIC ...

  4. keil5 mdk调用外部编辑器notepad++、sublime3、VSCode总结

    1.打开keil主界面,点击菜单栏Tools菜单,选择如下图所示的选项. 2.点击如下图所示的菜单上红笔标注的地方,给这个工具命名,如notepad++.sublime3.vscode等,如下图, 并 ...

  5. powerpoint教程资料,PPT的

    Powerpoint,是微软公司设计的演示文稿软件,利用Powerpoint不仅可以创建演示文稿,还可以在互联网上召开面对面会议.远程会议或在网上给观众展示演示文稿,掌握利用PowerPoint是一项 ...

  6. Spring BindingResult验证框架Validation特殊用法

    使用注解@Valid(实体属性校验) Springboot实现 Spring实现 一.准备校验时使用的JAR validation-api-1.0.0.GA.jar:JDK的接口: hibernate ...

  7. 学习RUNOOB.COM进度一

    了解MongoDB 由C++语言编写的,是一个基于分布式文件存储的开源数据库系统.在高负载的情况下,添加更多的节点,可以保证服务器性能. 特点 面向文档,操作简单容易 设置任何索引,实现更快排序 本地 ...

  8. c++ map的使用方法

    1.头文件:#include<map> 2.定义:map<typename1,typename2> mp 注:字符串数组只能用string而不能使用char[] 3.访问方式: ...

  9. [Cracking the Coding Interview] 4.2 Minimal Tree 最小树

    Given a sorted(increasing order) array with unique integer elements, write an algorithm to create a ...

  10. Scala Tuple

    Python中的Tuple 元组将多样的对象集合到一起,元素不能修改,通过索引进行查找, 使用括号"()" 允许重复 Scala中的Tuple 概念跟Python是完全相同的 定义 ...