生活随笔
收集整理的這篇文章主要介紹了
BZOJ1415[Noi2005]聪聪和可可——记忆化搜索+期望dp
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述
輸入
數據的第1行為兩個整數N和E,以空格分隔,分別表示森林中的景點數和連接相鄰景點的路的條數。 第2行包含兩個整數C和M,以空格分隔,分別表示初始時聰聰和可可所在的景點的編號。 接下來E行,每行兩個整數,第i+2行的兩個整數Ai和Bi表示景點Ai和景點Bi之間有一條路。 所有的路都是無向的,即:如果能從A走到B,就可以從B走到A。 輸入保證任何兩個景點之間不會有多于一條路直接相連,且聰聰和可可之間必有路直接或間接的相連。
輸出
輸出1個實數,四舍五入保留三位小數,表示平均多少個時間單位后聰聰會把可可吃掉。
樣例輸入
【輸入樣例1】
4 3
1 4
1 2
2 3
3 4
【輸入樣例2】
9 9
9 3
1 2
2 3
3 4
4 5
3 6
4 6
4 7
7 8
8 9
樣例輸出
【輸出樣例1】
1.500
【輸出樣例2】
2.167
提示
【樣例說明1】
開始時,聰聰和可可分別在景點1和景點4。
第一個時刻,聰聰先走,她向更靠近可可(景點4)的景點走動,走到景點2,然后走到景點3;假定忽略走路所花時間。
可可后走,有兩種可能:
第一種是走到景點3,這樣聰聰和可可到達同一個景點,可可被吃掉,步數為1,概率為 。
第二種是停在景點4,不被吃掉。概率為 。
到第二個時刻,聰聰向更靠近可可(景點4)的景點走動,只需要走一步即和可可在同一景點。因此這種情況下聰聰會在兩步吃掉可可。
所以平均的步數是1* +2* =1.5步。
對于所有的數據,1≤N,E≤1000。
對于50%的數據,1≤N≤50。
總體來說不是太難,只要把題里需要的信息都求出來按題目要求做就行。 SPFA求出以每個點為源點的最短路并用一個數組記錄每個點能到達的點有哪些順便維護出每個點的度。 通過前兩個信息就能求出從一個點到另一個點的途中下一步會走向哪個點。 因為最終結束狀態不確定,我們可以記憶化搜索,f[i][j]代表聰聰在i點,可可在j點時聰聰抓到可可的期望時間,按題目要求轉移就行了。 具體實現看代碼吧。 #include<set>
#include<map>
#include<queue>
#include<cmath>
#include<stack>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define ld long double
#define pr pair<int,int>
using namespace std;
int tot;
int vis[1010];
int head[1010];
int to[2010];
int next[2010];
double f[1010][1010];
int d[1010][1010];
int n,m;
int x,y;
int a,b;
int g[1010];
int w[1010][1010];
int p[1010][1010];
queue<int>q;
void add(int x,int y)
{tot++;next[tot]=head[x];head[x]=tot;to[tot]=y;
}
void SPFA(int S)
{memset(d[S],0x3f,sizeof(d[S]));d[S][S]=0;q.push(S);while(!q.empty()){int now=q.front();q.pop();vis[now]=0;for(int i=head[now];i;i=next[i]){if(d[S][to[i]]>d[S][now]+1){d[S][to[i]]=d[S][now]+1;if(!vis[to[i]]){vis[to[i]]=1;q.push(to[i]);}}}}
}
double dfs(int s,int t)
{if(f[s][t]!=0){return f[s][t];}if(s==t){return f[s][t]=(double)0;}if(p[p[s][t]][t]==t){return f[s][t]=(double)1;}if(p[s][t]==t){return f[s][t]=(double)1;}for(int i=1;i<=g[t];i++){f[s][t]+=dfs(p[p[s][t]][t],w[t][i])/(g[t]+1);}f[s][t]+=dfs(p[p[s][t]][t],t)/(g[t]+1);f[s][t]+=1;return f[s][t];
}
int main()
{scanf("%d%d%d%d",&n,&m,&a,&b);for(int i=1;i<=m;i++){scanf("%d%d",&x,&y);add(x,y);add(y,x);g[x]++;g[y]++;w[x][g[x]]=y;w[y][g[y]]=x;}for(int i=1;i<=n;i++){SPFA(i);}memset(p,0x7f,sizeof(p));for(int i=1;i<=n;i++){for(int j=1;j<=g[i];j++){for(int k=1;k<=n;k++){if(d[i][k]==d[w[i][j]][k]+1&&p[i][k]>w[i][j]){p[i][k]=w[i][j];}}}}printf("%.3f",dfs(a,b));
}
轉載于:https://www.cnblogs.com/Khada-Jhin/p/9948611.html
總結
以上是生活随笔為你收集整理的BZOJ1415[Noi2005]聪聪和可可——记忆化搜索+期望dp的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。