UVa #1252 Twenty Questions (例题9-16)

本文介绍了一种使用动态规划算法解决“二十问”问题的方法。该算法通过集合上的动态规划来减少重复计算,并利用子问题的解来构建更复杂问题的解答。文中详细解释了状态定义、动态规划过程及其实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.5s低空飘过


集合上的动态规划,中间状态一般就是全集的子集合。为了精确的描述状态,一般增加一个或多个维度。


这道题全集就是所有的特征,中间状态就是询问了某一些特征。询问的结果则要用另一个维度来储存。


动态规划的过程就是把所有可能的询问遍历一遍,在每次遍历的同时,遍历所有的询问结果的可能性。边界值及时返回、重叠子问题及时返回,避免重复运算。



Run Time: 2.542s

#define UVa  "LT9-16.1252.cpp"		//Twenty Questions
char fileIn[30] = UVa, fileOut[30] = UVa;

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<ctype.h>

using namespace std;

//Global Variables. Reset upon Each Case!
const int maxm = 11 + 1, maxn = 128 + 5;
const int INF = maxm + 5;
int m, n;
int ft[maxn];
int cnt[1<<maxm][1<<maxm];
int d[1<<maxm][1<<maxm];
/////

int dp(int s, int a) {
    if(d[s][a] != -1) return d[s][a];
    int& ans = d[s][a];
    if(cnt[s][a] == 1) return ans = 0;
    ans = INF;
    for(int i = 0; i < m; i ++) {
        int f = 1<<i;
        if(!(s&f)) {
            int d1 = dp(s|f, a);
            int d2 = dp(s|f, a|f);
            ans = min(ans, max(d1, d2) + 1);
        }
    }
    return ans;
}

int main() {
    while(scanf("%d%d", &m, &n) && m) {
        char ch;
        memset(ft, 0, sizeof(ft));
        memset(cnt, 0, sizeof(cnt));
        memset(d, -1, sizeof(d));
        for(int i = 0; i < n; i ++) {
            for(int j = 0; j < m; j ++) {
                do{ch = getchar();}while(!isalnum(ch));
                ft[i] = ft[i] * 2 + ch - '0';
            }
        }
        for(int s = 0; s <= (1<<m)-1; s ++) {   //O(n*2^m)
            for(int i = 0; i < n; i ++) {
                int tmp = s & ft[i];
                cnt[s][tmp] ++;
            }
        }
        printf("%d\n", dp(0,0));                //O(m*3^m)
                                                //Total: O(n*2^m + m*3^m)
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值