[填坑]期望概率DP 試煉場
阿新 • • 發佈:2017-10-18
double ems %0 練習 can mage set www print
完成了新手村任務的Hallmeow,來到了試煉場提升自己
正當我在網上找題練習的時候,突然意識到原來的題庫裏有這個專項,但我一共沒做幾道題而且還渾渾噩噩的,OD找的題質量都沒話說,於是就把這些弄懂吧
[試煉場]BZOJ 1415 聰聰與可可
聰聰可以一下走兩步,而且聰聰先走,可可後走
我們預處理出來p[ i ][ j ]為聰聰在 i ,可可在 j 時聰聰下一步要走到哪,用n遍spfa即可
顯然,dp[ i ][ i ]=0
顯然,如果p[ i ][ j ]= j 或者 p[ p[ i ][ j ] ][ j ]= j 那麽沒等到可可走就被吃掉了,dp[ i ][ j ]=1
設 w 為與 j 有連邊的點, t 為 j 的度
需要記憶化搜索,用已經更新的更新未更新的
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; #define pos(i,a,b) for(int i=(a);i<=(b);i++) #define pos2(i,a,b) for(int i=(a);i>=(b);i--) #define N 2000 struct haha{ int next,to; }edge[N]; int head[N],cnt=1; int degree[N]; void add(int u,int v){ degree[u]++; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; } int n,m; int a,b; int dis[N],flag[N]; int p[N][N]; void spfa(int st) { int f[N],q[65540],v[N],from[N]; unsigned short r,h; int i; memset(f,0x3f,sizeof f); f[st]=0;q[++r]=st; while(r!=h) { int x=q[++h]; v[x]=0; for(i=head[x];i;i=edge[i].next) if(f[edge[i].to]>f[x]+1||f[edge[i].to]==f[x]+1&&x<from[edge[i].to]) { f[edge[i].to]=f[x]+1; from[edge[i].to]=x; if(!v[edge[i].to]) v[edge[i].to]=1,q[++r]=edge[i].to; } } for(i=1;i<=n;i++) if(i!=st) p[i][st]=from[i]; } double ans[N][N]; double dfs(int x,int y){ if(x==y) return ans[x][y]=0; if(p[x][y]==y) return ans[x][y]=1; if(p[p[x][y]][y]==y) return ans[x][y]=1; if(ans[x][y]>=-1e-7) return ans[x][y]; double re=1.0;int temp=p[p[x][y]][y]; for(int i=head[y];i;i=edge[i].next){ re+=dfs(temp,edge[i].to)/(degree[y]+1); } re+=dfs(temp,y)/(degree[y]+1); return ans[x][y]=re; } int main(){ scanf("%d%d%d%d",&n,&m,&a,&b); pos(i,1,m){ int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } pos(i,1,n){ spfa(i); } memset(ans,200,sizeof(ans)); printf("%0.3lf",dfs(a,b)); return 0; }
[填坑]期望概率DP 試煉場