题链:

http://www.lydsy.com/JudgeOnline/problem.php?id=3640
题解:

期望dp,高斯消元
设dp[i][h]在i位置且血量为h这个状态的期望经过次数。
因为每当到达n点就停止游戏,所以到达终点的概率就是dp[n][1]+dp[n][2]+...+dp[n][hp]
可以按血量把dp分成若干个层次,我们希望这样分层次后就可以把问题转变为DAG上的dp,
可是存在伤害值为0的点,所以我们对于每一层列出来的n的dp计算式,是可能存在环的。
所以要用高斯消元。复杂度(hp*N^3)
注意到在每个层次做高斯消元时,其实这些方程的系数都相同,
(规定一下方程的形式:a1*x1+a2*x2+a3*x3+...+an*xn=c,a都为系数,x为n个未知数,c为常数项)
所以我们可以预处理记录下高斯消元是怎么消的,或者说,
因为每个未知数一定是由n个常数项线性组合起来的,所以我们记录一下每个未知数是如何由n个方程的常数项构成的
具体做法是把n个常数项看成一个1×n的X矩阵,然后把每个未知数xi分别也看成1×n的一个矩阵Yi
然后如果知道了常数项的矩阵,就可以由Yi*X的倒置矩阵得到一个1×1的矩阵,而里面存的值就是xi的值。
所以高斯消元就是去求出这n个Yi矩阵。
复杂度:O(hp*n^2+n^3)
更详细的膜这里:https://blog.sengxian.com/solutions/bzoj-3640

代码:

#include<bits/stdc++.h>
#define MAXN 160
using namespace std;
const double eps=1e-12;
double ANS,a[MAXN][MAXN],*A[MAXN],dp[MAXN][10005];
int damage[MAXN],cnt[MAXN];
int N,M,HP;
int dcmp(double x){
if(fabs(x)<eps) return 0;
return x>0?1:-1;
}
struct Edge{
int ent;
int to[MAXN*MAXN],nxt[MAXN*MAXN],head[MAXN];
Edge():ent(2){}
void Adde(int u,int v){
to[ent]=v; nxt[ent]=head[u]; head[u]=ent++;
}
}E;
struct Matrix{
int r,c;
double a[2][MAXN];
void Reset(int _r,int _c){
r=_r; c=_c;
memset(a,0,sizeof(a));
}
Matrix operator - () const{
Matrix now; now.Reset(r,c);
for(int i=1;i<=now.r;i++)
for(int j=1;j<=now.c;j++)
now.a[i][j]=-a[i][j];
return now;
}
Matrix operator + (const Matrix &rtm) const{
Matrix now; now.Reset(r,c);
for(int i=1;i<=now.r;i++)
for(int j=1;j<=now.c;j++)
now.a[i][j]=a[i][j]+rtm.a[i][j];
return now;
}
Matrix operator - (const Matrix &rtm) const{
return *this+(-rtm);
}
Matrix operator * (const double k) const{
Matrix now; now.Reset(r,c);
for(int i=1;i<=now.r;i++)
for(int j=1;j<=now.c;j++)
now.a[i][j]=a[i][j]*k;
return now;
}
Matrix operator & (const Matrix &rtm) const{ //乘上rtm的倒置矩阵
Matrix now; now.Reset(r,rtm.r);
for(int i=1;i<=now.r;i++)
for(int j=1;j<=now.c;j++)
for(int k=1;k<=c;k++)
now.a[i][j]+=a[i][k]*rtm.a[j][k];
return now;
}
Matrix operator / (const double k) const{
return *this*(1/k);
}
}B[MAXN],c[MAXN],X;
Matrix *C[MAXN];
void buildequation(){
for(int i=1;i<=N;i++){
a[i][i]=-1; if(damage[i]) continue;
for(int e=E.head[i];e;e=E.nxt[e]){
int j=E.to[e]; if(j==N) continue;
a[i][j]+=1.0/cnt[j];
}
}
for(int i=1;i<=N;i++){
B[i].Reset(1,N); A[i]=a[i];
c[i].Reset(1,N); c[i].a[1][i]=1;
C[i]=&c[i];
}
}
void Gausselimination(int pos,int i){
if(pos==N+1||i==N+1) return;
for(int j=pos;j<=N;j++) if(dcmp(A[j][i])!=0){
swap(A[pos],A[j]); swap(C[pos],C[j]); break;
}
if(dcmp(A[pos][i])!=0)
for(int j=pos+1;j<=N;j++){
double k=A[j][i]/A[pos][i];
for(int l=i;l<=N;l++)
A[j][l]-=A[pos][l]*k;
(*C[j])=(*C[j])-(*C[pos])*k;
}
Gausselimination(pos+(dcmp(A[pos][i])!=0),i+1);
if(dcmp(A[pos][i])!=0){
for(int l=i+1;l<=N;l++)
B[i]=B[i]+B[l]*A[pos][l];
B[i]=(*C[pos])-B[i];
B[i]=B[i]/A[pos][i];
}
}
int main(){
ios::sync_with_stdio(0);
cin>>N>>M>>HP;
for(int i=1;i<=N;i++) cin>>damage[i];
for(int i=1,u,v;i<=M;i++){
cin>>u>>v;
E.Adde(u,v),cnt[u]++;
if(u!=v) E.Adde(v,u),cnt[v]++;
}
buildequation();
Gausselimination(1,1);
for(int h=HP;h>=1;h--){
X.Reset(1,N);
for(int i=1;i<=N;i++){
if(!damage[i]) continue;
if(h+damage[i]>HP) continue;
for(int e=E.head[i];e;e=E.nxt[e]){
int j=E.to[e]; if(j==N) continue;
X.a[1][i]-=dp[j][h+damage[i]]*1.0/cnt[j];
}
}
if(h==HP) X.a[1][1]-=1;
for(int i=1;i<=N;i++)
dp[i][h]=(B[i]&X).a[1][1];
ANS+=dp[N][h];
}
cout<<fixed<<setprecision(8)<<ANS<<endl;
return 0;
}

  

●BZOJ 3640 JC的小苹果的更多相关文章

  1. BZOJ 3640: JC的小苹果 [概率DP 高斯消元 矩阵求逆]

    3640: JC的小苹果 题意:求1到n点权和\(\le k\)的概率 sengxian orz的题解好详细啊 容易想到\(f[i][j]\)表示走到i点权为j的概率 按点权分层,可以DP 但是对于\ ...

  2. BZOJ 3640: JC的小苹果

    3640: JC的小苹果 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 425  Solved: 155[Submit][Status][Discus ...

  3. BZOJ 3640 JC的小苹果(逆矩阵)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3640 题意:给出一个无向图,从1走到n.开始是血量H,从u到达v时血量减少a[v] ...

  4. 3640: JC的小苹果 - BZOJ

    让我们继续JC和DZY的故事.“你是我的小丫小苹果,怎么爱你都不嫌多!”“点亮我生命的火,火火火火火!”话说JC历经艰辛来到了城市B,但是由于他的疏忽DZY偷走了他的小苹果!没有小苹果怎么听歌!他发现 ...

  5. 【BZOJ】3640: JC的小苹果

    题解 我们考虑列出期望方程组,\(dp[i][j]\)表示在第\(i\)个点血量为\(j\)的时候到达\(N\)点的概率,所有的\(dp[N][j]\)都是1,所有\(j < 0\)都是0 答案 ...

  6. 【BZOJ 3640】JC的小苹果 (高斯消元,概率DP)

    JC的小苹果 Submit: 432  Solved: 159 Description 让我们继续JC和DZY的故事. “你是我的小丫小苹果,怎么爱你都不嫌多!” “点亮我生命的火,火火火火火!” 话 ...

  7. 【BZOJ3640】JC的小苹果 概率DP+高斯消元

    [BZOJ3640]JC的小苹果 Description 让我们继续JC和DZY的故事. “你是我的小丫小苹果,怎么爱你都不嫌多!” “点亮我生命的火,火火火火火!” 话说JC历经艰辛来到了城市B,但 ...

  8. bzoj千题计划291:bzoj3640: JC的小苹果

    http://www.lydsy.com/JudgeOnline/problem.php?id=3640 dp[i][j] 表示i滴血到达j的概率 dp[i][j] = Σ dp[i+val[i]][ ...

  9. BZOJ3640 : JC的小苹果

    设$f[i][j]$表示$hp$为$i$,在$j$点的概率,$d[i]$表示$i$的度数,$w[i]$表示经过$i$点要扣掉的血量. 对于$j$到$k$这条边,$f[i-w[k]][k]+=\frac ...

随机推荐

  1. webView调用系统地图,电话,和跳转链接的方法

    webView.dataDetectorTypes = UIDataDetectorTypePhoneNumber | UIDataDetectorTypeLink | UIDataDetectorT ...

  2. maven创建web工程

    使用eclipse插件创建一个web project 首先创建一个Maven的Project如下图 我们勾选上Create a simple project (不使用骨架) 这里的Packing 选择 ...

  3. git cherry-pick 整理

    git cherry-pick可以选择某一个分支中的一个或几个commit(s)来进行操作.例如,假设我们有个稳定版本的分支,叫v2.0,另外还有个开发版本的分支v3.0,我们不能直接把两个分支合并, ...

  4. 织梦cms网上复制图片不可用的解决方法

    背景描述: 织梦cms采集图片集时, 需要使用织梦cms提供的"网上复制图片"的功能, 好像我这里这个功能一直不可用, 今天下定决心研究了下源代码并进行了适当修改, 将我的修改提供 ...

  5. vue 中获取select 的option的value 直接click?

    我刚开始遇到这个问题的时候 直接用的click进行dom操作获取value 但是发现并灭有什么作用 问了旁边大神 才想起来还有change这个操作 于是乎 答案有了解决方案 1.在你的select中添 ...

  6. UML开发工具Rose ralation的破解安装,

    UML开发工具Rose ralation的在windows764破解安装, 安装下载还可以参考:http://www.cnblogs.com/leaven/p/3718361.html 跟大家分享怎么 ...

  7. python+flask 分分钟完美解析阿里云日志

    拿到了自己阿里云服务器的日志,对其需要进行处理. class Read_Rizhi: def __init__(self,filename): self.filename=filename def o ...

  8. New UWP Community Toolkit - DropShadowPanel

    概述 UWP Community Toolkit  中有一个为 Frmework Element 提供投影效果的控件 - DropShadowPanel,本篇我们结合代码详细讲解  DropShado ...

  9. Step by Step 真正从零开始,TensorFlow详细安装入门图文教程!帮你完成那个最难的从0到1

    摘要: Step by Step 真正从零开始,TensorFlow详细安装入门图文教程!帮你完成那个最难的从0到1 安装遇到问题请文末留言. 悦动智能公众号:aibbtcom AI这个概念好像突然就 ...

  10. 说说Java代理模式

    代理实现可以分为静态代理和动态代理. 静态代理 静态代理模式其实很常见,比如买火车票这件小事:黄牛相当于是火车站的代理,我们可以通过黄牛买票,但只能去火车站进行改签和退票.在代码实现中相当于为一个委托 ...