您的位置:首页 > 其它

uva 11825 状态压缩DP

2014-05-31 21:53 330 查看
妈蛋啊 一开始一直以为是树形dp的。。。。。

然后这题其实可以转化成状态压缩DP

Pi表示第i个点可以覆盖到的点

然后不就有了p1 p2 p3.。。。pn嘛

然后就是求最多可以分成多少组使每组并起来是全集

然后dp[s]表示集合s可以分成多少组

然后dp[s] = max(dp[s0])+ 1

s0是s的子集

so。。。。。

AC代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int N, M, p[20];
int dp[1<<20];
int cover[1<<20];

bool judge( int s ){
int temp = 0;
if( cover[s] != -1 ){
return cover[s];//不记忆一下会TLE
}
for( int i = 0; i < N; i++ ){
if( ( 1 << i ) & s ){
temp |= p[i];
}
}
if( temp == ( 1 << N ) - 1 ){
return cover[s] = true;
}else{
return cover[s] = false;
}
}

int main(){
int Case = 1;
while( scanf( "%d", &N ) && N ){
for( int i = 0; i < N; i++ ){
scanf( "%d", &M );
int t = 1 << i;
for( int j = 0; j < M; j++ ){
int temp;
scanf( "%d", &temp );
t |= 1 << temp;
}
p[i] = t;
}
dp[0] = 0;
memset( cover, -1, sizeof( cover ) );
for( int i = 0; i < ( 1 << N ); i++ ){
dp[i] = 0;
for( int s = i; s ; s = i & ( s - 1 ) ){
if( judge( s ) ){
dp[i] = max( dp[i], dp[i^s] + 1 );
}
}
}
printf( "Case %d: %d\n", Case++, dp[(1<<N)-1] );
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: