Problem F Codeforces 16E

这道题是一道数位Dp将鱼的死活列为0两种状态然后找DP关系

•题意:有n(n<=18)条鱼,接下来的n-1天,每天会有一对鱼(a,b)相遇,每天任意一对鱼相遇的概率是相等的,相遇之后,他们其中的一条会吃掉另外一条。
•鱼a吃掉鱼b的概率是p,那么鱼b吃掉鱼a的概率就是1-p;
•给你一个n*n的矩阵,表示n条鱼中的某对相遇时,互相吃掉对方的概率。
•数据保证pij+pji=1;
•计算每只鱼最后存活下来的概率。
•status{x1,x2,x3,x4,………xn-1,xn}表示每只鱼是否还活着的状态
•xi=1表示第i条鱼还活着
•xi=0表示第i条鱼已经被吃掉了
•dp(status)表示形成status这种状态的概率
•那么刚开始的时候(第一天),所有的鱼都活着。
•那么dp({1,1,1,1….,1,1,1})=1。
•假设当前状态status活着的鱼有t条
•此时,如果鱼j活着,鱼k也活着,那么j把k吃掉的概率是多少呢?
•P(j吃掉k)=P(j,k相遇)*P(相遇时j可以吃掉k)=1/C(t,2)*P(相遇时j可以吃掉k)
•dp(newstatus) += P(j吃掉k)*dp(status)
•newstatus:j吃掉k之后的新状态
 
 
题目代码:
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 double dp[1<<18];
 7 double map[18][18];
 8 int bitCount(int n)//数位上的组合数,将n转化成进制,来看里面有多少个,代表有多少条鱼
 9 {
10     int cnt=0;
11     while(n){
12         if(n&1) cnt++;
13         n>>=1;
14     }
15     return cnt;
16 }
17 
18 int main()
19 {
20     int n,t;
21     while(scanf("%d",&n)!=EOF){
22         memset(dp,0,sizeof(dp));
23         for(int i=0;i<n;i++)
24             for(int j=0;j<n;j++)
25                 scanf("%lf",&map[i][j]);
26         dp[(1<<n)-1]=1.000000;
27         for(int i=(1<<n)-1;i>=1;i--){
28             t=bitCount(i);
29             if(t==1) continue;
30             for(int j=0;j<n;j++){
31                 if((1<<j)&i){
32                     for(int k=0;k<n;k++){
33                         if((1<<k)&i)
34                             dp[i^(1<<k)]+=2*dp[i]/t/(t-1)*map[j][k];
35                     }
36                 }
37             }
38         }
39         for(int i=0;i<n;i++) printf("%0.6f ",dp[1<<i]);
40         printf("\n");
41     }
42     return 0;
43 }
View Code

 

 posted on 2014-07-27 21:52  Love风吟  阅读(240)  评论(0编辑  收藏  举报