Posted on 2008-01-16 03:09 
oyjpart 阅读(1266) 
评论(3)  编辑 收藏 引用  所属分类: 
ACM/ICPC或其他比赛 
			 
			
		 
		第一题,纯暴搞的题,应当要写的更快些。
第二题。DP。题目稍些复杂。不用说了,我这等菜鸟,又是挂掉了。。sigh...
依靠一个cha,颜色变黄。
corret solution :
const int N = 15;
int dp[two(N)];
int adj[N];
int n;
int go(int x) {
 int i, k, j;
 int &ret = dp[x];
 if(ret != -1) return ret;
 
 int all = 0;
 for(i = 0; i < n; ++i) {
  if(contains(x, i)) {
   all |= adj[i];
  }
 }
 if(all != two(n)-1) return ret = 0;
 ret = 1;
 int b[N];
 for(i = 0, k = 0; i < n; ++i) if(contains(x, i)) b[k++] = i;
 for(i = 0; i < two(k)-1; ++i) {
  int y = 0, z = 0;
  for(j = 0; j < k; ++j) {
   if(contains(i, j)) y |= two(b[j]);
   else z |= two(b[j]);
  }
  ret = Max(ret, go(y) + go(z));         // 注意 表面上貌似这一行被引用了2^n*2^k次,但实际上只有3^n (利用均摊分析的思想,相当于分成了3个集合)
 }
 return ret;
}
class InformFriends
{ 
public: 
 int maximumGroups(vector <string> f) 
 { 
  n = sz(f);
  memset(adj, 0, sizeof(adj));
  int i, j;
  for(i = 0; i < n; ++i) {
   adj[i] |= two(i);
   for(j = 0; j < n; ++j) {
    if(f[i][j] == 'Y')
     adj[i] |= two(j);
   }
  }
  memset(dp, -1, sizeof(dp));
  return go(two(n)-1);
 } 
 赛后看到其他很多人的代码,很有趣,各种各样的都有
比如通过 for(i = 0; i < (1<<n); (i+mask+1)&~mask) 来寻找mask补集的子集
也有 for(i = ~mask&(1<<n); i > 0; i = (i-1)&mask) 的