计蒜客 NOIP模拟赛(3) D1T1火山喷发


火山喷发对所有附近的生物具有毁灭性的影响。在本题中,我们希望用数值来模拟这一过程。


在环境里有 nnn 个生物分别具有 A1,A2,⋯,An​​点生命值,一次火山喷发总计 M轮,每轮造成 1点伤害,等概率地分给所有存活的生物,即如果目前有 K 个活着的生物,每个生物受到这点伤害的概率是 1/K​​。如果一个生物的生命值减为 0,它会立即死去,此后都不会再占用受到伤害的概率。如果没有生物存活,那么将没有生物会受到伤害。


现在你的任务是,给定 n,M 和全部生物的生命值,问每个生物火山喷发后依然存活的概率。


输入格式
第一行两个正整数 n 和 M。
第二行 n 个正整数 A1,...,An。


输出格式
n行,第 i 行一个数表示第 i 个生物存活下来的概率,保留小数点后六位。


数据范围与约定
对于 10% 的数据 N=1。
对于 30% 的数据 N=2。
对于全部数据 N≤4,M≤120,A​i​​≤50。


样例输入1

1 2
1

样例输出1

0.000000

样例输入2

3 15
2 12 2

样例输出2

0.001684
0.996632
0.001684
f[i][j][k][p]表示生命值为i,j,k,p时的概率

那么我们枚举轮数和4个生物的HP,就可以转移

但是O(120*50^4)显然超时

但我们知道轮数和3个生物的HP,显然可以推出第四个

所以O(120*50^3)就够了

还有要注意枚举的HP对应的损失HP必须等于轮数

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 double cnt,f[51][51][51][51],ans;
 7 int n,a[5],m;
 8 int main()
 9 {int l,i,j,k,p;
10     cin>>n>>m;
11     for (i=1;i<=n;i++)
12         scanf("%d",&a[i]);
13  m=min(m,a[1]+a[2]+a[3]+a[4]);
14  f[a[1]][a[2]][a[3]][a[4]]=1;
15     for (l=0;l<=m;l++)
16     {
17         for (i=0;i<=a[1];i++)
18         {
19             for (j=0;j<=a[2];j++)
20             {
21                 for (k=0;k<=a[3];k++)
22                 {
23                     int p=a[4]-(l-(a[1]-i)-(a[2]-j)-(a[3]-k));
24                     if (a[1]-i+a[2]-j+a[4]-p+a[3]-k!=l) continue; 
25                     if (p<0||p>a[4]) continue;
26                     if (f[i][j][k][p]==0) continue;
27                     cnt=0;
28                     if (i) cnt++;if (k) cnt++;
29                     if (j) cnt++;if (p) cnt++;
30                    if (cnt==0) continue;
31                     if (i) f[i-1][j][k][p]+=f[i][j][k][p]/cnt;
32                     if (j) f[i][j-1][k][p]+=f[i][j][k][p]/cnt;
33                     if (k) f[i][j][k-1][p]+=f[i][j][k][p]/cnt;
34                     if (p) f[i][j][k][p-1]+=f[i][j][k][p]/cnt;
35                 }
36             }
37         }
38     }  
39   for (i=1;i<=n;i++)
40   {ans=0;
41       if (i==1)
42           for (j=0;j<=a[2];j++)
43           for (k=0;k<=a[3];k++)
44           for (p=0;p<=a[4];p++)
45               if (a[1]+a[2]-j+a[3]-k+a[4]-p==m)
46              ans+=f[0][j][k][p];
47        if (i==2)
48           for (j=0;j<=a[1];j++)
49           for (k=0;k<=a[3];k++)
50           for (p=0;p<=a[4];p++)
51               if (a[1]-j+a[2]+a[3]-k+a[4]-p==m)
52              ans+=f[j][0][k][p];
53        if (i==3)
54           for (j=0;j<=a[1];j++)
55           for (k=0;k<=a[2];k++)
56           for (p=0;p<=a[4];p++)
57               if (a[1]-j+a[2]-k+a[3]+a[4]-p==m)
58              ans+=f[j][k][0][p];
59        if (i==4)
60           for (j=0;j<=a[1];j++)
61           for (k=0;k<=a[2];k++)
62           for (p=0;p<=a[3];p++)
63               if (a[1]-j+a[2]-k+a[3]-p+a[4]==m)
64              ans+=f[j][k][p][0];
65    printf("%.6lf\n",1-ans);
66   }
67 }

 

posted @ 2017-09-11 12:49  Z-Y-Y-S  阅读(416)  评论(0编辑  收藏  举报