Luogu P2973 [USACO10HOL]赶小猪Driving Out the Piggi 后效性DP

有后效性的DP:$f[u]$表示到$u$的期望次数,$f[u]=\Sigma_{(u,v)} (1-\frac{p}{q})*f[v]*deg[v]$,最后答案就是$f[u]*p/q$

刚开始$f[1]=1$,,因为炸弹初始在$1$号节点。所以增广矩阵中$a[1][n+1]=1$。

系数矩阵$a[i][i]$赋值为1,其他点的系数写成负数,相当于是所有的加起来$=0$.

#include<cstdio>
#include<iostream>
#include<cmath>
#define R register int
#define db long double
using namespace std;
const db eps=1E-13;
const int N=310;
db a[N][N],P;
int mp[N][N],r[N],n,m,p,q;
inline int g() {
    R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
}
inline bool ck0(const db& x) {return x<eps&&x>-eps;}
inline void Gauss(int n) {
    for(R i=1;i<=n;++i) { R p=i;
        for(R j=i+1;j<=n;++j) if(ck0(a[p][i])||fabs(a[p][i])<fabs(a[j][i])) p=j;
        if(p!=i) swap(a[p],a[i]);
        for(R j=i+1;j<=n;++j) if(!ck0(a[j][i])) {
            register db t=a[j][i]/a[i][i];
            for(R k=1;k<=n+1;++k) a[j][k]-=t*a[i][k];
        }
    } for(R i=n;i>=1;--i) {
        for(R j=n;j>i;--j) a[i][n+1]-=a[i][j]*a[j][n+1];
        a[i][n+1]/=a[i][i];
    }
}
signed main() {
    n=g(),m=g(),p=g(),q=g(); P=(db)p/q;
    for(R i=1,u,v;i<=m;++i) u=g(),v=g(),mp[u][v]=mp[v][u]=1,++r[u],++r[v];
    for(R i=1;i<=n;++i) a[i][i]=1;
    for(R i=1;i<=n;++i) for(R j=1;j<=n;++j) if(mp[i][j]) a[i][j]-=(1.0-P)/r[j];
    a[1][n+1]=1; Gauss(n); for(R i=1;i<=n;++i) printf("%.9Lf\n",a[i][n+1]*P);
} 

2019.05.24

 

转载于:https://www.cnblogs.com/Jackpei/p/10912273.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值