utsubo’s blog

競技プログラミングとか.

100問マラソン 4問目 SRM 663 Div2 Hard: CheeseRolling

問題

http://community.topcoder.com/stat?c=problem_statement&pm=13919
優勝するトーナメントのパターン云々

解法

kmjpさんのを見させて頂きました.
TopCoder SRM 663 Div2 Hard CheeseRolling - kmjp's blog

#include <bits/stdc++.h>
using namespace std;

class CheeseRolling{
public:
	long long dp[16][1<<16];
	vector<long long> waysToWin(vector<string> wins){
		memset(dp,0,sizeof(dp));
		int n = wins.size();

		//一人の時に1を代入しておく
		for(int i=0;i<n;i++){
			dp[i][1<<n] = 1;
		}

		for(int mask=1;mask<1<<n;mask++){
			int bc = __builtin_popcount(mask);
			//2^i以外は必要ない
			if(bc & (bc-1) || bc == 1)continue;

			for(int mask2=mask;mask2>0;mask2=(mask2-1)&mask){
				int bc2 = __builtin_popcount(mask2);
				//部分集合を半分ずつの部分集合に分割
				if(bc*2 != bc)continue;
				int mask3 = mask ^ mask2;
				for(int x=0;x<n;x++) if(dp[x][mask2]) for(int y=0;y<n;y++) if(dp[y][mask3]){
					if(wins[y][x] == 'Y')
						dp[y][mask] += dp[x][mask2] * dp[y][mask3];
					else
						dp[x][mask] += dp[x][mask2] * dp[y][mask3];
				}
			}
			
		}

		vector<long long> ret;
		for(int i=0;i<n;i++){
			ret.push_back(dp[i][(1<<n)-1]);
		}
		return ret;
	}
};

理解は出来たが,今後活かせる程ではないのでもう少し考える.