Twenty Questions UVA - 1252

題目傳送門

思路:這個題目很巧妙啊,一看就是一個狀壓DP,但是這個題我覺得難點在於如何求得狀態轉移以後的狀態,一開始想了很久都沒有想出來,然後看了lrj的書上寫的,確實十分的巧妙,我們用dp[s][a]來表示當前已經詢問了集合s的問題,具有集合a特徵的還要詢問最少多少次才能求得最優解,然後我們可以預處理一個數組來記錄每一個狀態下有多少個滿足的物體。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <sstream>

#define MAXN 150
#define MAXE 11
#define MAX_SIZE 8
#define INF 0x3fffffff
#define EPS 1e-6
#define MOD 1000000007
#define LL long long
#define ULL unsigned long long
#define pi 3.14159

using namespace std;

int n, m;
int arr[MAXN];
int dp[(1 << MAXE) + 10][(1 << MAXE) + 10];
int num[(1 << MAXE) + 10][(1 << MAXE) + 10];

int change(const string &str) {
    int ans = 0;
    for (int i = 0; i < str.length(); ++i) {
        ans = ans * 2 + str[i] - '0';
    }
    return ans;
}

void init() {
    memset(num, 0, sizeof(num));
    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j < (1 << m); ++j) {
            num[j][j & arr[i]]++;
        }
    }
    memset(dp, -1, sizeof(dp));
}

int DFS(int s, int a) {
    int &ans = dp[s][a];
    if (ans > -1) {
        return ans;
    }
    if (num[s][a] == 1) {
        return ans = 0;
    } else if (num[s][a] == 2) {
        return ans = 1;
    }
    ans = m;
    for (int i = 0; i < m; ++i) {
        if (!(s & (1 << i)) && num[s | (1 << i)][a | (1 << i)] && num[s | (1 << i)][a]) {
            int temp = max(DFS(s | (1 << i), a), DFS(s | (1 << i), a | (1 << i))) + 1;
            ans = min(ans, temp);
        }
    }
    return ans;
}

int main() {
    std::ios::sync_with_stdio(false);
    while (cin >> m >> n) {
        if (n == 0 && m == 0) {
            break;
        }
        string str;
        for (int i = 1; i <= n; ++i) {
            cin >> str;
            arr[i] = change(str);
        }
        init();
        cout << DFS(0, 0) << endl;
    }
    return 0;
}

/*
 8 1
 11010101
 11 4
 00111001100
 01001101011
 01010000011
 01100110001
 11 16
 01000101111
 01011000000
 01011111001
 01101101001
 01110010111
 01110100111
 10000001010
 10010001000
 10010110100
 10100010100
 10101010110
 10110100010
 11001010011
 11011001001
 11111000111
 11111011101
 11 12
 10000000000
 01000000000
 00100000000
 00010000000
 00001000000
 00000100000
 00000010000
 00000001000
 00000000100
 00000000010
 00000000001
 00000000000
 9 32
 001000000
 000100000
 000010000
 000001000
 000000100
 000000010
 000000001
 000000000
 011000000
 010100000
 010010000
 010001000
 010000100
 010000010
 010000001
 010000000
 101000000
 100100000
 100010000
 100001000
 100000100
 100000010
 100000001
 100000000
 111000000
 110100000
 110010000
 110001000
 110000100
 110000010
 110000001
 110000000
 0 0
 */
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章