• 计蒜客 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
    ",1-ans);
    66   }
    67 }
  • 相关阅读:
    php使用redis的有序集合zset实现延迟队列
    php使用redis的几种常见方式和用法
    redis缓存雪崩,缓存穿透,缓存击穿的解决方法
    php操作redis数据库方法总结
    mysql 悲观锁与乐观锁的理解
    OAuth2.0 协议的理解
    windows下的mongodb安装与配置
    node.js中对 redis 的安装和基本操作
    node.js中对 mysql 进行增删改查等操作和async,await处理
    node.js中 koa 框架的基本使用方法
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7504433.html
Copyright © 2020-2023  润新知