TopCoder SRM 388 Div1 Medium InformFriends
問題
N人の友達がいる。
N人のそれぞれが互いに友達であるかはfriends[]により与えられる。
友達に噂を出来るだけ多くの個数だけ伝えたい。
一人の友達につき、伝えられる噂の数は1つだけである。
噂を聞いた友達は、自分の友達にだけその噂を伝える(その友達の友達には伝わらない)。
このとき、全員が共有できる噂の数の最大値を求めよ。
制約条件
N≦15
方針
友達から「同じ噂を伝える人の集合」を一つ決める。
すると、その集合に対して一つの噂を伝えたときに、全員に伝わるかそうでないかがわかる。
dp[mask]を、そのmask集合の人に噂を伝え終えた後での、全員に伝わった噂の数の最大値とすると、
全員に伝わるような友達の選び方iについて、
dp[mask]=max(dp[mask^i]+1)が成り立つ。
なので、部分集合に対して更新していくようなDPをすれば答えがO(3^n)で求まる。
ソースコード
bool ok[1<<15]; int dp[1<<15]; class InformFriends { public: int maximumGroups(vector <string> friends) { int n=friends.size(); rep(i,1<<n){ int mask=i; rep(j,n)rep(k,n) if((i&1<<j)&&friends[j][k]=='Y')mask|=1<<k; ok[i]=mask==(1<<n)-1; } memset(dp,0,sizeof(dp)); rep(i,1<<n)for(int j=i;j;j=(j-1)&i) dp[i]=max(dp[i],dp[i^j]+ok[j]); return dp[(1<<n)-1]; } };