uva_11825_Hackers' Crackdown (狀態壓縮DP,好題)

分析:
這個題目的數學模型是,把集合p1, p2, p3, ..., pn分儘量多組,使得每組的並集等於S全集,其中pi表示i於i相鄰的頂點組成的集合,每組等於一個服務
把一個集合表示二進制的形式,狀態f[i]表示i所表示的集合最多分成多少組
f[i] = max(f[j]| j的並集等於S)+1
Code:
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;


#define DIR     4
#define DIM     2
#define STATUS  2
#define MAXN    1<<17
#define MAXM    100000 + 10
#define oo      (~0u)>>1
#define INF     0x3F3F3F3F
#define REPI(i, s, e)   for(int i = s; i <= e; i ++)
#define REPD(i, e, s)   for(int i = e; i >= s; i --)


static const double EPS = 1e-5;


int f[MAXN], cover[MAXN], each[17];


int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
        freopen("test.in", "r", stdin);
#endif
        int n, m, v, cnt(1), terminal;
        while( scanf("%d", &n) ) {
                if( !n ) {
                        break;
                }


                //init each
                REPI(i, 0, n-1) {
                        each[i] = (1<<i);
                        scanf("%d", &m);
                        REPI(j, 1, m) {
                                scanf("%d", &v);
                                each[i] |= (1<<v);
                        }
                }


                //init cover
                REPI(i, 0, (1<<n)-1) {
                        cover[i] = 0;
                        REPI(j, 0, n-1) {
                                if( i&(1<<j) ) {
                                        cover[i] |= each[j];
                                }
                        }
                }


                //f[s] = max(f[sub_set]| cover[sub_set]=terminal)+1
                terminal = (1<<n)-1;
                REPI(s, 0, (1<<n)-1) {
                        f[s] = 0;
                        for(int sub_set = s; sub_set; sub_set = (sub_set-1)&s) {
                                if( terminal == cover[sub_set] ) {
                                        f[s] = max(f[s], f[s^sub_set]+1);
                                }
                        }
                }
                printf("Case %d: %d\n", cnt ++, f[terminal]);
        }
        return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章