UVa 1252

有n个物体的m个特征,每个物体用m位的01串表示,每次可以询问一个特征,问最少询问几次可以保证猜到

思路

状态压缩、动态规划

用两维表示,d(s, a),s表示已经询问的特征集,a表示已经具备的特征集,设要询问的下一个特征为k

min{ max{ d(s + {k}, a + {k}), d(s + {k}, a)  + 1} }

边界是当有个物体符合a,不符合s-a中的特征,d(s, a) = 0

#include <bits/stdc++.h>
using namespace std;
const int maxn = 128 + 5;
const int maxs = 12;
int m, n;
int f[maxn];
int d[1<<maxs][1<<maxs];
int cnt[1<<maxs][1<<maxs];
bool vis[1<<maxs][1<<maxs];
int bitchange(const char *s){
    int sum = 0;
    for(int i = m - 1, j = 0; i >= 0; --i, ++j) {
        if(s[i] == '1') sum |= (1 << j);
    }
    return sum;
}

int judge(int s, int a) {
    int & val = cnt[s][a];
    if(val != -1) return val;
    val = 0;
    for(int i = 0; i < n; ++i) {
        int s_a = ((~a) & s);
        if((f[i] & a) == a && (s_a & f[i]) == 0)
            val++;
    }
    return val;
}

int dp(int s, int a) {
    int & ans = d[s][a];
    if(vis[s][a]) return ans;
    vis[s][a] = true;
    if(judge(s, a) == 1) return ans = 0;
    ans = m;
    for(int i = 0; i < m; ++i) if((s & (1 << i)) == 0){
        int s0 = s | (1 << i), a0 = a | (1 << i);
        ans = min(ans, max(dp(s0, a0), dp(s0, a)) + 1);
    }
    return ans;
}
int main()
{
    while(scanf("%d%d",&m, &n) == 2){
        if(m == 0 && n == 0) break;
        memset(vis, false, sizeof(vis));
        char s[20];
        for(int i = 0; i < n; ++i) {
            scanf("%s", s);
            f[i] = bitchange(s);
        }
        memset(cnt, -1, sizeof(cnt));
        printf("%d\n", dp(0, 0));
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值