【动态规划23】hdu5036 Explosion(bitset优化)

题目描述

有n个房间,每个房间中都放有一些钥匙,每个钥匙都能打开且仅能打开一个房间的门。对于无法直接用钥匙打开的门可以用炸弹炸开,求打开所有门使用炸弹次数的期望。

输入输出格式

The first line of the input contains an integer T, denoting the number of testcases. Then T test cases follow.
In the first line of each test case, there is an integer N (N<=1000) indicating the number of rooms.
The following N lines corresponde to the rooms from 1 to N. Each line begins with an integer k (0<=k<=N) indicating the number of keys behind the door. Then k integers follow corresponding to the rooms these keys can open.
For each test case, output one line “Case #x: y”, where x is the case number (starting from 1), y is the answer which should be rounded to 5 decimal places.

对于开每个箱子之后能开出的所有箱子的集合用bitset预处理
假设每个箱子能通过开k个箱子开出来,那么每次能通过炸开某个箱子来打开这个箱子的概率就是 kn ,也就相当于需要使用 nk 次炸弹才能打开这个箱子,将所有次数加在一起后除以n即为期望。

#include<bits/stdc++.h>
#define fer(i,j,n) for(int i=j;i<=n;i++)
#define far(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define pa pair<int,int>
const int maxn=1010;
const int INF=1e9+7;
using namespace std;
/*----------------------------------------------------------------------------*/
inline ll read()
{
    char ls;ll x=0,sng=1;
    for(;ls<'0'||ls>'9';ls=getchar())if(ls=='-')sng=-1;
    for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';
    return x*sng;
}
/*----------------------------------------------------------------------------*/
int n;
bitset<maxn> f[maxn];
int main()
{
    int T=read();
    fer(t,1,T)
    {
        n=read();
        fer(i,1,n)
        {
            f[i].reset();
            f[i][i]=1;  
        }
        fer(i,1,n)
        {
            int k=read();
            fer(j,1,k)
            {
                int x=read();
                f[i][x]=1;  
            }
        }
        fer(i,1,n)
            fer(j,1,n)
                if(f[j][i])
                f[j]|=f[i];
        double ans=0;
        fer(i,1,n)
        {
            int cnt=0;
            fer(j,1,n)if(f[j][i])cnt++;
            ans+=(double)1/cnt; 
        }
        printf("Case #%d: %.5lf\n",t,ans);  
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值