题目: 给出一个无向图, 求出其中的最大团.
题解: 最大团是一个NP完全问题...这道题爆搜+优化就能过. 爆搜是枚举所有子图(当然要是团). 优化是加入一个记忆化搜索的数组f, f[i]表示i-n这些点中能组成的最大团点数. 然后记忆化搜的时候如果当前枚举到i时(还没选i)的最大团点数 + f[i]小于全局最大团(已求得的最大团)的话, 就continue. 还有就是如果当前能选的点+已有最大团 < 全局最大团的话也return.
#include<stdio.h>
#define N 55
int n, ans, mp[N][N], f[N], now[N];
void dfs(int u, int sum){
if(sum > ans) ans = sum;
int able = 0, tnow[N];
for(int i = u + 1; i <= n; ++i){
tnow[i] = now[i];
if(now[i]) able++;
}
if(sum + able <= ans) return;
for(int i = u + 1; i <= n; ++i){
if(!tnow[i]) continue;
if(f[i] + sum <= ans) continue;
for(int j = u + 1; j <= n; ++j)
now[j] = tnow[j] & mp[i][j];
dfs(i, sum + 1);
}
}
inline int Max_Clique(){
ans = f[n] = 1;
for(int i = n - 1; i; --i){
for(int j = 1; j <= n; ++j)
now[j] = mp[i][j];
dfs(i, 1);
f[i] = ans;
}
return ans;
}
int main(){
while(~scanf("%d", &n) && n){
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
scanf("%d", &mp[i][j]);
printf("%d\n", Max_Clique());
}
}