zoukankan      html  css  js  c++  java
  • 2012百度之星冬季赛第四场第二题 度熊的复仇

    题目:

    度熊的复仇

     

    Time Limit: 1 Seconds   Memory Limit: 65536K

     

    度熊是个喜欢打DOTA的人,有一天他打DOTA的时候被对面的拉比克完全压制,于是他决定选一个自己的拉比克去报仇。

    现在,度熊的面前有很多敌人,他可以选择对任意一个敌人施放“弱化能流”。“弱化能流”有连锁反应,连锁的时候伤害不会减弱。如果这个人被击中了那么和他距离在D以内的敌人也会同时被击中,同时会一直这样连锁下去直到条件不满足。每次施放“弱化能流”只会对同一个敌人造成1次伤害,当敌人的血量小于等于0时这个敌人就会死去,但是依然存在,就是说还是可以继续被连锁和向外连锁。

    度熊的拉比克有个特性就是有“一击必杀”,当他每次施放“弱化能流”时会有p%的概率触发此特性,那么此次的伤害将会直接变成无穷大,同时其余特性不变,即依然有连锁性而且连锁的伤害依然是无穷大。

    现在有N个敌人,每个敌人的血是Ki(1 <= i <= n),每次“弱化能流”造成的伤害是Att,每次施放需要消耗m的魔法值。

    现在度熊想知道:他把所有敌人全部消灭的魔法消耗期望值是多少?

     

    Input

    第一行输入一个T代表有T组样例(T <= 20)。

    每个样例的第一行输入5个整数n,att,m,p,D,代表有n个敌人,每次“弱化能流”造成的伤害是att,需要消耗m的魔法值,有p%的概率会造成一击必杀,两人的距离在D以内时可以被连锁(1 <= n <= 1000 , 1 <= att <= 100 , 1 <= m <= 10 , 0 <= p <= 100,1 <= D <= 100000)。

    接下来n行,每行包含3个整数xi,yi,ki,代表度熊的敌人的位置在(xi,yi),他的血是ki,度熊的敌人可以认为是一个点(1 <= xi,yi <= 150000, 1 <= ki <= 100)。

     

    Output

    对于每个样例,请输出"Case #c : ans".

    "c"代表着是第几个样例,样例从1开始;

    "ans"代表消灭所有敌人需要消耗的期望魔法值,要求保留两位小数。

     

    Sample Input

    2

    3 1 1 10 5

    0 0 5

    1 1 7

    2 2 10

    4 1 4 13 3

    0 0 6

    1 1 8

    9 9 7

    10 10 9

     

    Sample Output

    Case #1: 6.51

    Case #2: 42.65

     

    特别注意:本题中距离在D以内,意为距离小于D。。。。(导致主号WA的关键句,不过第二天考试RP++了)

     

      首先可以发现,如果很多人连成一片的话,攻击其中任意一个都是等价的。然后就等价于攻击期中K最大的人。

      怎么划分集合,我用的是并查集的方法。

      然后对每个集合,取出其中最大的K,求出没有“一击必杀”需要多少次才能打死。假设计算出来为x次,那么x次打死的概率为(1.0 - p)^(k-1)

      其他的,假设i次打死(i<x),概率为(10. - p)^(i - 1) * p

      乘上次数统计期望。然后各个集合全部相加就好。

    代码:

     1 #include<cmath>
     2 #include<cstdio>
     3 using namespace std;
     4 typedef long long ll;
     5 int T,C,n,a,m,f[1001],k[1001];
     6 ll d;
     7 double p,ans;
     8 struct poi{
     9     int x,y;
    10     void in(){scanf("%d%d",&x,&y);}
    11     ll jl(const poi &b)const{
    12         ll i=x-b.x,j=y-b.y;
    13         return i*i+j*j;
    14     }
    15 }s[1001];
    16 int gf(int x){return x!=f[x]?f[x]=gf(f[x]):x;}
    17 void lk(int i,int j){
    18     int x=gf(i),y=gf(j);
    19     f[x]=y;
    20     if(k[x]>k[y])k[y]=k[x];
    21 }
    22 double ga(int k){
    23     k=k/a+(k%a?1:0);
    24     double a1=0.0,ap=1.0;
    25     for(int i=1;i<k;i++){
    26         a1+=i*ap*p;
    27         ap*=1.0-p;
    28     }
    29     return a1+pow(1.0-p,k-1)*k;
    30 }
    31 int main()
    32 {
    33     scanf("%d",&T);
    34     while(T--){
    35         scanf("%d%d%d%lf%lld",&n,&a,&m,&p,&d);
    36         p/=100.0;
    37         d*=d;
    38         for(int i=0;i<n;i++){
    39             s[i].in();
    40             f[i]=i;
    41             scanf("%d",k+i);
    42         }
    43         for(int i=0;i<n;i++)
    44         for(int j=i+1;j<n;j++)
    45             if(s[i].jl(s[j])<=d)lk(i,j);
    46         ans=0.0;
    47         for(int i=0;i<n;i++)if(f[i]==i)ans+=ga(k[i]);
    48         printf("Case #%d: %.2lf\n",++C,ans*m);
    49     }
    50     return 0;
    51 }
  • 相关阅读:
    Windows创建多个github git ssh秘钥
    Kafka(三)自动提交存在的问题?
    Kafka(二)关于Kafka设置(spring.kafka.consumer.enable-auto-commit=false)依然提交消息确认的offset问题分析。
    Kafka(一)集群搭建以及常用命令可视化工具
    CPU相关信息操作
    Nginx系列篇
    DB2——临时表
    DB2sql——insert all与insert first用法讲解与实例
    DB2sql——通过查询结果来create table 的3种方式
    DB21019E An error occurred while accessing the directory "/root".
  • 原文地址:https://www.cnblogs.com/hundundm/p/2856921.html
Copyright © 2011-2022 走看看