1. 程式人生 > >bzoj 1415 [NOI2005]聰聰與可可 (概率DP+dfs)

bzoj 1415 [NOI2005]聰聰與可可 (概率DP+dfs)

print 預處理 %20 front sum 移動 ++ printf for

題目大意:給你一個無向聯通圖,節點數n<=1000。聰聰有一個機器人從C點出發向在M點的可可移動,去追趕並吃掉可可,在單位時間內,機器人會先朝離可可最近的節點移動1步,如果移動一步機器人並不能吃掉可可,那機器人會再向可可的方向移動一格,如果有兩個節點到可可的距離相等,那機器人會移動到編號較小的一個節點。然後可可會等可能性移動到與它的任意一個相連的節點或者原地不動(即使她明知道移動到某個節點會被吃掉)。即1/(outc[x]+1),outc為出度。求可可被吃掉時機器人走的期望時間

概率DP記憶化+遞歸

先預處理出任意兩點距離

接下來遞歸求答案,記錄一個f[x][y]表示可可在x節點,機器人在y節點時,可可被吃掉的期望時間,x,y這種局面可能出現多次,由不同的前驅狀態到達x,y這種狀態,所以乘上前驅狀態轉移到當前狀態的概率,就是這個情況對前驅狀態答案的貢獻。

對於每種狀態,答案都是技術分享圖片,prob是前驅狀態轉移到當前狀態的的概率

時間是技術分享圖片

 1 #include <queue>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define N 1010
 6 #define mod 20100403
 7 #define p(i,j) ((i-1)*m+j)
 8 #define dd double
 9 using namespace std;
10 
11 char str[N][N];
12 int n,m,s,e,cte;
13 int inc[N],ouc[N],d[N][N],head[N],use[N]; 14 dd f[N][N]; 15 struct Edge{int to,nxt;}edge[N*10]; 16 void ae(int u,int v){ 17 ++cte,edge[cte].to=v,inc[v]++,ouc[u]++; 18 edge[cte].nxt=head[u],head[u]=cte; 19 } 20 void bfs() 21 { 22 memset(d,0x3f,sizeof(d)); 23 for(int i=1;i<=n;i++) 24
{ 25 d[i][i]=0; 26 queue<int>q; 27 q.push(i),use[i]=1; 28 memset(use,0,sizeof(use)); 29 while(!q.empty()) 30 { 31 int x=q.front();q.pop(); 32 for(int j=head[x];j!=-1;j=edge[j].nxt){ 33 int v=edge[j].to; 34 if(d[i][v]>d[i][x]+1){ 35 d[i][v]=d[i][x]+1; 36 if(!use[v]) use[v]=1,q.push(v); 37 } 38 }use[x]=0; 39 } 40 } 41 } 42 dd dfs(int x,int y,dd pb) 43 { 44 int vx,to1,to2; 45 dd ans=1.0; 46 if(f[x][y]-0.000000001>0) return f[x][y]*pb; 47 if(!d[x][y]) {f[x][y]=0;return 0;} 48 if(d[x][y]<=2) {f[x][y]=1.0;return pb*1.0;} 49 to1=y; 50 for(int j=head[y];j!=-1;j=edge[j].nxt){ 51 int v=edge[j].to; 52 if(d[x][v]<d[x][to1]) to1=v; 53 else if(d[x][v]==d[x][to1]) to1=min(v,to1); 54 } 55 to2=to1; 56 for(int j=head[to1];j!=-1;j=edge[j].nxt){ 57 int v=edge[j].to; 58 if(d[x][v]<d[x][to2]) to2=v; 59 else if(d[x][v]==d[x][to2]) to2=min(v,to2); 60 } 61 for(int j=head[x];j!=-1;j=edge[j].nxt){ 62 vx=edge[j].to; 63 ans+=dfs(vx,to2,1.0/(1.0*ouc[x]+1.0)); 64 } 65 ans+=dfs(x,to2,1.0/(1.0*ouc[x]+1.0)); 66 f[x][y]=ans; 67 return ans*pb; 68 } 69 70 int main() 71 { 72 scanf("%d%d%d%d",&n,&m,&s,&e); 73 int x,y;memset(head,-1,sizeof(head)); 74 for(int i=1;i<=m;i++) 75 scanf("%d%d",&x,&y), 76 ae(x,y),ae(y,x); 77 bfs(); 78 printf("%.3lf\n",dfs(e,s,1.0)); 79 return 0; 80 }

bzoj 1415 [NOI2005]聰聰與可可 (概率DP+dfs)