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之后的新状态
题目代码:
View Code
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 }
我还在坚持,我还未达到我所想,梦~~一直在