1. 程式人生 > >【算法總結】概率與期望相關

【算法總結】概率與期望相關

else tle 選擇 def mem html ros 也不能 algorithm

〖相關資料

《淺析競賽中一類數學期望問題的解決方法》

〖相關題目

1.【bzoj1415】[NOI2005] 聰聰和可可

題意:在一個魔法森林裏,住著一只聰明的小貓聰聰和一只可愛的小老鼠可可。整個森林可以認為是一個無向圖,圖中有N 個美麗的景點,景點從1 至N編號。在景點之間有一些路連接。可可正在景點M (M ≤ N)處。以後的每個時間單位,可可都會選擇去相鄰的景點(可能有多個)中的一個或停留在原景點不動。而去這些地方所發生的概率是相等的。聰聰是很聰明的,所以,當她在景點C 時,她會選一個更靠近可可的景點,如果這樣的景點有多個,她會選一個標號最小的景點。如果走完第一步以後仍然沒吃到可可,她還可以在本段時間內再向可可走近5一步。

在每個時間單位,假設聰聰先走,可可後走。在某一時刻,若聰聰和可可位於同一個景點,則可可就被吃掉了。問平均情況下,聰聰幾步就可能吃到可可。

分析:bfs預處理+概率dp。詳見:湯可因《淺析競賽中一類數學期望問題的解決方法》。

技術分享圖片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int N=1e3+10;
 6 int n,m,u,v,cat,mouse,cnt,head,tail;
 7 int first[N],ind[N],q[N],dis[N][N],p[N][N];
8 double f[N][N]; 9 struct edge{int to,next;}e[N*2]; 10 int read() 11 { 12 int x=0,f=1;char c=getchar(); 13 while(c<0||c>9){if(c==-)f=-1;c=getchar();} 14 while(c>=0&&c<=9){x=x*10+c-0;c=getchar();} 15 return x*f; 16 } 17 void ins(int u,int v){e[++cnt]=(edge){v,first[u]};first[u]=cnt;}
18 void bfs(int S) 19 { 20 head=tail=0;q[tail++]=S; 21 p[S][S]=dis[S][S]=0; 22 while(head!=tail) 23 { 24 u=q[head++];if(head>1000)head=0; 25 for(int i=first[u];i;i=e[i].next) 26 { 27 v=e[i].to; 28 if(dis[S][u]+1<dis[S][v]||(dis[S][u]+1==dis[S][v]&&p[S][u]<p[S][v])) 29 { 30 dis[S][v]=dis[S][u]+1; 31 if(dis[S][v]<=1)p[S][v]=v; 32 else p[S][v]=p[S][u]; 33 q[tail++]=v;if(tail>1000)tail=0; 34 } 35 } 36 } 37 } 38 double dfs(int a,int b) 39 { 40 if(f[a][b])return f[a][b]; 41 if(a==b)return f[a][b]=0; 42 if(p[a][b]==b||p[p[a][b]][b]==b)return f[a][b]=1; 43 double sum=dfs(p[p[a][b]][b],b); 44 for(int i=first[b];i;i=e[i].next) 45 sum+=dfs(p[p[a][b]][b],e[i].to); 46 return f[a][b]=sum/(ind[b]+1)+1; 47 } 48 int main() 49 { 50 memset(p,0x3f,sizeof(p));memset(dis,0x3f,sizeof(dis)); 51 n=read();m=read();cat=read();mouse=read(); 52 for(int i=1;i<=m;i++) 53 u=read(),v=read(),ind[u]++,ind[v]++,ins(u,v),ins(v,u); 54 for(int i=1;i<=n;i++)bfs(i); 55 printf("%.3lf",dfs(cat,mouse)); 56 return 0; 57 }
View Code

2.【bzoj1076】[SCOI2008]獎勵關

題意:在獎勵關裏,系統依次隨機拋出k次寶物,每次可以選擇吃或者不吃(必須在拋出下一個寶物之前做出選擇,且現在決定不吃的寶物以後也不能再吃)。寶物一共有n種,每次拋出這n種寶物的概率都相同且相互獨立。獲取第i種寶物將得到Pi分,但第i種寶物有一個前提寶物集合Si。只有當Si中所有寶物都至少吃過一次,才能吃第i種寶物。假設你采取最優策略,平均情況你一共能在獎勵關得到多少分值?

分析:為了方便地判斷狀態是否合法,可以倒著枚舉。

技術分享圖片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int N=16;
 6 const int M=(1<<15)+10;
 7 int m,n,x,mx,v[N],t[N],p[N];
 8 double f[105][M];
 9 int read()
10 {
11     int x=0,f=1;char c=getchar();
12     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
13     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
14     return x*f;
15 }
16 int main()
17 {
18     m=read();n=read();p[1]=1;mx=(1<<n)-1;
19     for(int i=2;i<=n;i++)p[i]=p[i-1]<<1;
20     for(int i=1;i<=n;i++)
21     {
22         v[i]=read();x=read();
23         while(x)t[i]|=p[x],x=read();
24     }
25     for(int i=m;i>=1;i--)
26         for(int j=0;j<=mx;j++)
27         {
28             for(int k=1;k<=n;k++)
29                 if((t[k]|j)==j)f[i][j]+=max(f[i+1][j],f[i+1][j|p[k]]+v[k]);
30                 else f[i][j]+=f[i+1][j];
31             f[i][j]/=n;
32         }
33     printf("%.6lf",f[1][0]);
34     return 0;
35 }
View Code

3.【bzoj4318】OSU!

題意:見原題。

分析:Clove_uniqueの博客

技術分享圖片
 1 #include<cstdio>
 2 #include<algorithm> 
 3 #include<cstring>
 4 #define LL long long
 5 using namespace std;
 6 const int N=1e5+5;
 7 int n;
 8 double p,f[N],g[N],h[N];
 9 int read()
10 {
11     int x=0,f=1;char c=getchar();
12     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
13     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
14     return x*f;
15 }
16 int main()
17 {
18     n=read();
19     for(int i=1;i<=n;i++)
20     {
21         scanf("%lf",&p);
22         h[i]=p*(h[i-1]+1);
23         g[i]=p*(g[i-1]+2*h[i-1]+1);
24         f[i]=p*(f[i-1]+3*g[i-1]+3*h[i-1]+1)+(1-p)*f[i-1];
25     }
26     printf("%.1lf",f[n]);
27     return 0;
28 }
View Code

【算法總結】概率與期望相關