【bzoj3270】博物馆
同样是高斯消元,我写的版本就受到了歧视
我怎么又犯把 $j$ 打成 $i$ 这种 $sb$ 错误
题意
一张无向图,两个人分别从 $s_1$ 号点和 $s2$ 号点开始,每轮两人都会同时进行一次以下操作:有 $p_i$ 的概率留在原地,剩下的 $1-p_i$ 的概率等概率随机选择一条出边走到连向的点。问两人在每个点相遇的概率(边上不相遇)。
$n\le 20$
题解
首先得知道,这种题的概率就是期望,因为在点 $i$ 相遇($1\le i\le n$)的期望和是 $1$,总概率也是 $1$。
期望和概率的一个重要差别就是期望可以不在 $[0,1]$ 范围内,之后转化的时候记住了。
这种题都有一种特性,就是感觉可以拓扑排序 $dp$。
但拓扑排序只适用于 $DAG$(有向无环图),对于有环图(包括无向图),没法确定 $dp$ 转移顺序。
好了,现在我们降低自己的智商,回到小学状态,想想在小学时你怎么做这种难题。
如果你学过小学奥数(没学过也无所谓吧),应该能想到列方程。
那方程是什么?就是我们的 $dp$ 式子,因为我们只是不确定转移顺序,但式子肯定是对的。
众所周知,方程是互相之间都有约束性的,解必须同时满足所有方程,所以可以解决没法确定转移顺序的情况。
所以这是高斯消元入门题。
由于 $n\le 20$,时间空间都随便用,先不用管会不会爆。
考虑正常 $dp$,设 $f(i,j)$ 表示两人分别在点 $i,j$ 的概率。
那 $f(i,j)$ 可以从它自己及所有直接相连的点转移过来。
我们再枚举哪个点转 $x$ 移到点 $i$,哪个点 $y$ 转移到点 $j$。
分类讨论,
当 $i=x,\space j=y$ 时,从 $f(x,y)$ 转移到 $f(i,j)$ 的概率是 $p_x\times p_y$;
当 $i=x,\space j≠y$ 时,从 $f(x,y)$ 转移到 $f(i,j)$ 的概率是 $p_x\times (1-p_y)/du_y$;
当 $i≠x,\space j=y$ 时,从 $f(x,y)$ 转移到 $f(i,j)$ 的概率是 $(1-p_x)\times p_y/du_x$;
当 $i≠x,\space j≠y$ 时,从 $f(x,y)$ 转移到 $f(i,j)$ 的概率是 $(1-p_x)\times (1-p_y)/du_x/du_y$;
其中 $du_x$ 表示点 $x$ 的度(就是有多少个点与它直接相连),注意点 $x$ 自己不算。
我们把所有的 $f(i,j)\space |\space 1\le i\le n,\space 1\le j\le n$ 都看作一个未知数,这样方程组共有 $n^2$ 个未知数,并且我们知道一个未知数表示的二元组(就是两人的位置)到另一个未知数表示的二元组的概率,也就是转移系数(其实就是系数,比如状态 $A$ 有 $k$ 的概率转移到 $B$,方程中就是 $B=kA$)是多少,这样就可以把所有转移系数列成矩阵,解方程组了。
一行方程大概长这样(区分了一下 $i,x$ 和 $j,y$) $$f(i,j) \space =\space f(i,j)\times ... + f(i,y)\times ... + f(x,j)\times ... + f(x,y)\times ...$$
把等号左边的 $f(i,j)$ 移到右边得到 $$0 \space =\space f(i,j)\times ... + f(i,y)\times ... + f(x,j)\times ... + f(x,y)\times ... - f(i,j)$$
也就是对于转移到的状态 $f(i,j)$,它对应的那行方程 等号右边的 $f(i,j)$ 那项的系数先减 $1$。
这个移项处理是高斯消元的终点,把未知数统一移到一边,常数统一移到另一边,省得再判等号两边的未知数。
起点作为被转移项时,其方程的等号左边是 $-1$,因为两人一开始就都在起点,所以已经期望有 $1$ 次到达这种状态,等号右边(所有未知数那边)就加了 $1$,移项到另一边就变成减 $1$。
再注意一点,两人终止的状态不再往其它状态转移,即两人的转移来源点 $x$ 和 $y$ 不能相等。
#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define dwn(i,x,y) for(int i=x;i>=y;--i)
#define rep_e(i,u) for(int i=hd[u];i;i=e[i].nxt)
#define ll long long
#define N 22
#define eps 1e-7
using namespace std;
inline int read(){
int x=; bool f=; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=;
for(; isdigit(c);c=getchar()) x=(x<<)+(x<<)+(c^'');
if(f) return x;
return -x;
}
int n,m,a,b;
double p[N],dp[N*N][N*N],ans[N*N];
struct edge{int v,nxt;}e[(N*N)<<];
int hd[N],cnt,du[N];
inline void add(int u,int v){e[++cnt]=(edge){v,hd[u]}, hd[u]=cnt;}
inline int getCnt(int x,int y){return (x-)*n+y;}
bool Gauss(int n){
rep(i,,n){
int r;
//cout<<"wow:"<<i<<endl;
for(r=i; r<=n && fabs(dp[i][r])<eps; ++r); if(fabs(dp[i][r])<eps) return ;
/*
rep(i,1,n){
rep(j,1,n+1) cout<<dp[i][j]<<' ';
cout<<endl;
}*/
if(i^r) swap(dp[i],dp[r]);
/*
rep(i,1,n){
rep(j,1,n+1) cout<<dp[i][j]<<' ';
cout<<endl;
}*/
double div=dp[i][i];
//cout<<div<<endl;
rep(j,i,n+) dp[i][j]/=div;
rep(j,i+,n){
div=dp[j][i];
rep(k,i,n+)
dp[j][k]-=dp[i][k]*div;
}
}
/*
rep(i,1,n){
rep(j,1,n+1) cout<<dp[i][j]<<' ';
cout<<endl;
}*/
ans[n]=dp[n][n+];
dwn(i,n-,){
ans[i]=dp[i][n+];
rep(j,i+,n) ans[i]-=ans[j]*dp[i][j];
}
/*
rep(i,1,n){
ans[i]=dp[fd][n+1]/dp[fd][fd];
}*/
return ;
}
int main(){
n=read(),m=read(),a=read(),b=read();
int u,v,all=n*n;
rep(i,,n) add(i,i);
rep(i,,m)
u=read(),v=read(),
++du[u],++du[v],
add(u,v),add(v,u);
rep(i,,n)
cin>>p[i];
dp[getCnt(a,b)][all+]=-;
rep(i,,n)
rep(j,,n){
int cnt1=getCnt(i,j);
--dp[cnt1][cnt1]; //i=j时自己不能转移到自己,所以自己给自己的转移的期望次数-1
rep_e(ii,i)
rep_e(jj,j){
int x=e[ii].v, y=e[jj].v;
//cout<<"try:"<<i<<' '<<j<<' '<<x<<' '<<y<<endl;
if(x^y){
int cnt2=getCnt(x,y);
if(i==x && j==y) dp[cnt1][cnt2]+=p[i]*p[j];
else if(i==x) dp[cnt1][cnt2]+=p[i]*(-p[y])/du[y];
else if(j==y) dp[cnt1][cnt2]+=(-p[x])*p[j]/du[x];
else dp[cnt1][cnt2]+=(-p[x])*(-p[y])/du[x]/du[y];
//cout<<i<<' '<<j<<' '<<x<<' '<<y<<' '<<cnt1<<' '<<cnt2<<' '<<p[x]<<' '<<p[y]<<' '<<du[x]<<' '<<du[y]<<' '<<dp[cnt1][cnt2]<<endl;
}
}
} if(!Gauss(all)){printf("I AK IOI!\n"); return -;}
rep(i,,n) printf("%.6lf ",ans[getCnt(i,i)]);
return ;
}
/*
3 2 1 3
1 2
2 3
0.5
0.5
0.5
显然,ans[1]和ans[3]应该相等,否则就是程序写错了
*/
怎么网上那么多人写的代码都一个样(包括高斯消元部分),这么不求上进的吗?
我写的高斯消元跟他们不一样,一开始结果不对,我还以为我的高斯消元是错的。
后来调对了,才意识到只是被鄙视了而已,因为我跟其他人写的都不一样。
然后呢?
【bzoj3270】博物馆的更多相关文章
- BZOJ3270: 博物馆
3270: 博物馆 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 269 Solved: 147[Submit][Status][Discuss] ...
- BZOJ3270:博物馆(高斯消元)
Description 有一天Petya和他的朋友Vasya在进行他们众多旅行中的一次旅行,他们决定去参观一座城堡博物馆.这座博物馆有着特别的样式.它包含由m条走廊连接的n间房间,并且满足可以从任何一 ...
- BZOJ3270 博物馆(高斯消元+概率期望)
将两个人各自所在点视为状态,新建一个图.到达某个终点的概率等于其期望次数.那么高斯消元即可. #include<iostream> #include<cstdio> #incl ...
- BZOJ3270: 博物馆【概率DP】【高斯消元】
Description 有一天Petya和他的朋友Vasya在进行他们众多旅行中的一次旅行,他们决定去参观一座城堡博物馆.这座博物馆有着特别的样式.它包含由m条走廊连接的n间房间,并且满足可以从任何一 ...
- 【概率dp 高斯消元】bzoj3270: 博物馆
一类成环概率dp的操作模式 Description 有一天Petya和他的朋友Vasya在进行他们众多旅行中的一次旅行,他们决定去参观一座城堡博物馆.这座博物馆有着特别的样式.它包含由m条走廊连接的n ...
- bzoj3270 博物馆(期望+高斯消元)
Time Limit: 30 Sec Memory Limit: 128 MB 有一天Petya和他的朋友Vasya在进行他们众多旅行中的一次旅行,他们决定去参观一座城堡博物馆.这座博物馆有着特别的 ...
- [bzoj3270] 博物馆 [期望+高斯消元]
题面 传送门 思路 本题的点数很少,只有20个 考虑用二元组$S=(u,v)$表示甲在$u$点,乙在$v$点的状态 那么可以用$f(S)$表示状态$S$出现的概率 不同的$f$之间的转移就是通过边 转 ...
- bzoj3270博物馆——期望概率DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3270 设计一个状态表示两个人分别在两个点的状态,带个标号num[i][j]: 据此得到状态之 ...
- OI刷题录——hahalidaxin
16-3-25 —— bzoj 2049 [Sdoi2008]Cave 洞穴勘测:LCT入门 bzoj 2002 [Hnoi2010]Bounce 弹飞绵羊:LCT Tsinsen A1303. t ...
- 【BZOJ3270】博物馆 期望DP+高斯消元
[BZOJ3270]博物馆 Description 有一天Petya和他的朋友Vasya在进行他们众多旅行中的一次旅行,他们决定去参观一座城堡博物馆.这座博物馆有着特别的样式.它包含由m条走廊连接的n ...
随机推荐
- 《毛毛虫组》【Alpha】Scrum meeting 3
第二天 日期:2019/6/16 1.1 今日完成任务情况以及遇到的问题. 今日完成任务情况: 货物入库管理模块设计: (1)对数据库表--tb_InStore进行修改并完善: (2)学习SQL Se ...
- rem和em的区别
原文链接:http://caibaojian.com/rem-vs-em.html rem 单位如何转换为像素值 当使用 rem 单位,他们转化为像素大小取决于页根元素的字体大小,即 html 元素的 ...
- 字节跳动后端开发实习生面试(Python)
一面: 1.自我介绍. 2.介绍“工大小美”项目相关. 3.Python中的GIL(全局解释器锁),以及哪种情况下使用python的多线程性能有较大的提升. 4.项目中用到了SQLite数据库,如果有 ...
- vmware虚拟机安装Windows 7后虚拟机自动挂起
vmware虚拟机安装windows7后在一段时间中没有操作,虚拟机会自动挂起,是因为windows7中的设置的自动睡眠,打开[控制面板]=>[电源选项]=>[选择关闭显示器时间]将下面两 ...
- 利用sysbench工具测试MHA
利用sysbench工具测试MHA 1. sysbench准备数据 2. sysbench开始压测 3. master模拟意外宕机 4. mysqldb2 上观察mha状态 5. 手工failover ...
- 分享几个简单的技巧让你的 vue.js 代码更优雅
1. watch 与 computed 的巧妙结合 一个简单的列表页面. 你可能会这么做: created(){ this.fetchData() }, watch: { keyword(){ thi ...
- PHP分页类代码
今天为大家献上一段代码,这是一段php分页代码: <?php//创建分页类class Page { private $_all_num; ...
- 并查集:POJ1182-食物链(并查集比较高端的应用)
食物链 Time Limit: 1000MS Memory Limit: 10000K Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C ...
- MySQL使用yum安装
1.下载mysql的repo源 $ wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm 2.安装mysql-comm ...
- Linux学习-检验软件正确性
md5sum / sha1sum / sha256sum 目前有多种机制可以计算文件的指纹码,我们选择使用较为广泛的 MD5, SHA1 或 SHA256 加密机 制来处理,我们拿NTP 软件来检查看 ...