Clarke and package

克拉克是一名人格分裂患者.有一天克拉克分裂成  n 个人.  
每个克拉克有一些背包,这一天里每个克拉克都想选择一个背包出去野营.  
第  i 个克拉克有  ki 个背包,第  j 个背包装有价值为  ci,j 的物品,选到这个背包的概率为  pi,j/10000 .  
每个克拉克都选好背包后,他们决定选择最多  m 个价值和最大的背包单独拿出来,加以保护.  
不过有人跳出来说,如果这最多  m 个背包都丢了怎么办?你们得估计一下损失.  
于是克拉克们就得算出若这最多  m 个背包都丢失了,损失的价值的期望.
Input
第一行是两个正整数n, m(1≤n, m≤50)  
接下来输入n个克拉克的信息:  
对于第i个克拉克,第一行是一个正整数ki(1≤ki≤50),接下来ki行,每行两个正整数cj, pj(1≤cj≤1000000, 1≤pj≤10000, ∑ pj=10000)
Output
输出一个实数,若你的答案与标准答案的相对误差小于1e-5,则视为正确.即|输出-答案|/|答案| < 1e-5.
Input示例
2 1
2
3 5000
4 5000
2
5 5000
6 5000
Output示例
5.5000000000
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;

const int MAXN = 3000;
const int MAGIC_I = 10000;
const double MAGIC_D = 0.0001;

struct package
{
    int c, p, id;
} pac[MAXN];

bool cmp(const package &x, const package &y)
{
    return x.c < y.c;
}

int n, m;
int tmp[MAXN];
double dp[MAXN];

int main()
{
    cin >> n >> m;
    int k, tot = 0;
    double result = 0;
    for (int i = 1; i <= n; i++)
    {
		cin >> k;
        while (k--)
        {
            tot++;
			cin >> pac[tot].c >> pac[tot].p;
            pac[tot].id = i;
        }
    }

    sort(pac + 1, pac + 1 + tot, cmp);

    for (int i = tot; i; i--)
    {
        for (int j = 0; j < n; j++)
        {
            dp[j] = 0;
        }
        dp[0] = 1;

        for (int j = 1; j <= n; j++)
        {
            if (j != pac[i].id)
            {
                for (int k = n - 1; k; k--)
                {
                    dp[k] = dp[k] * (MAGIC_I - tmp[j]) * MAGIC_D + dp[k - 1] * tmp[j] * MAGIC_D;
                }
                dp[0] *= (MAGIC_I - tmp[j]) * MAGIC_D;
            }
        }

        for (int j = 0; j < m; j++)
        {
            result += dp[j] * pac[i].c * pac[i].p * MAGIC_D;
        }
        tmp[pac[i].id] += pac[i].p;
    }

    printf("%.8lf\n", result);

    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值