Referring to the above-mentioned solution, a total of three steps, the first two steps are better understood. P[i] is the number of digits to be overwritten when I is elected in bits, in total there are 0~n-1. Cover[s] Indicates the number of bits that can be overwritten in a 0~n-1 when the subset is S. If each bit of cover[s] is 1, then the subset S can cover the complete works, which may be done by a subset of subset S.
The key step is to understand the state transition equation. The state transfer equation in the book is F (S) =max{f (S0) | S0 is a subset of S, Cover[s0] is equal to the complete}+1, in fact, for this equation I always feel strange, do not quite understand its meaning, although it can finally AC. According to my own understanding the transfer equation should be like this,F (S) =max{f (S0) +f (S^S0) | S0 is a subset of S, Cover[s0] equals the complete set} and must ensure that cover[s] is complete, f (s) is at least 1, so that the value of f (s) is 1 when the S is the minimum covering sets. This solution, and finally can be AC, and I personally think the idea is more clear than the book.
As for why for (int s0=s; S0; s0= (s0-1) &s) can traverse all subsets of S, and the rigorous proof method is not yet thought. But intuitively, you can see. For example, S is 10101, then the S0 is 10101,10100,10001 .... We can completely ignore the middle 0, so the entire for loop becomes 111,110,101,100: This process is one-off. In fact, to think carefully is also, S0 minus a process, is the lowest non 0 position 0, and then will be lower than the position of all the bits are 1, after the s and after the low before the beginning of the appearance, so the whole process can be seen as a recursive cycle of the process. (It's not clear that ....) Self-simulation should be able to understand)
#include <iostream> #include <cstdio> #include <algorithm> #define MAX 16+5#define MAXN (1<<16 ) +5using namespace Std;int n,case=1;int cover[maxn],p[max],f[maxn];int main () {//freopen ("Data.txt", "R", stdin); while (cin>>n) {if (! N) break; for (int i=0;i<n;++i) {int m,x; cin>>m; p[i]=1<<i; while (m--) {cin>>x; P[i]|= (1<<x);} } for (int s=0; s< (1<<n); ++s) {cover[s]=0; for (int i=0;i<n;++i) {if (s& (1<<i)) cover[s]|=p[i];//get the overlay of the Subset S}} F[0] = 0; The int all= (1<<n) -1;//all represents the complete for (int s=1; s< (1<<n); ++s) {if (cover[s]==all) {f[s]=1; } else{f[s]=0; Continue } for (int s0=s; S0; s0= (s0-1) &s)//The subset of the enumeration S if (Cover[s0]==all) F[s]=max (F[s],f[s0^s]+f[s0]); } cout<< "Case" <<Case++<< ":" <<f[ALL]<<endl; } return 0;}
UVa 11825 Hackers ' crackdown