罪犯审问 暴力+记忆化 SRM 672 div2 1000Tdetectived2

题意

抓小偷,先从目击者0开始,选择犯罪可能性最大的一个人,如果有多人相同,选择哪个都有可能。然后更新所有人的犯罪可能性。

问如果一个人是小偷,最少几轮能被发现。

题解

暴力枚举,状态压缩DP

两重循环计算每个人的在所有人中的最大怀疑值,若等于指定人则更新答案。

int n;
vector<string> s;
 
int memo[18][1<<18];
 
int f(int k, int mask)
{
    int & res = memo[k][mask];
    if (res == -1) {
        int susp = -1;
        int best_time = 0;
         
        // get suspicions.
        // for the maximum suspicion, remember the minimum time
        for (int i = 1; i < n; i++) {
            if ( !( (1<<i) & mask) ) {
                int su = 0;
                for (int j = 0; j < n; j++) {
                    if ( (1<<j) & mask) {
                        su = std::max<int>(su, s[j][i] - '0');
                    }
                }
                int t = 1 + ( (i == k)? 0 : f(k, mask | (1<<i) )  );
                if (su > susp) {
                    // new maximum suspicion
                    susp = su;
                    best_time = t;
                } else if ( (su == susp) && (best_time > t) ) {
                    // update minimum time
                    best_time = t;
                }
            }
        }
        res = best_time;
    }
    return res;
}
 
int reveal(vector<string> s)
{
    // init memo table with -1s
    memset( memo, -1, sizeof(memo) );
    this->s = s;
    n = s.size();
     
    int res = 0;
     
    for (int i = 0; i < n; i++) {
        res += i * f(i, 1);
    }
    return res;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值