分析:
這個題目的數學模型是,把集合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;
}
uva_11825_Hackers' Crackdown (狀態壓縮DP,好題)
最新推荐文章于 2019-08-05 18:22:12 发布