给你一个无向图,让你找到这个图里面的最大团是多少。
思路:
最大图案是NP问题,直接暴力搜索,如果当前的这个点可以加入当前最大团,那么就选择加入或者舍去,如果不能加入,直接舍去,还有一个剪枝就是当前的答案+后面剩余所有点 小于 当前的全局最大 的话直接return.
自己写的跑了 4000+
#include<stdio.h> #define N 60 int map[N][N] ,n; int now[N] ,Ans; bool ok(int sum ,int to) { for(int i = 1 ;i <= sum ;i ++) if(!map[now[i]][to]) return 0; return 1; } void DFS(int to ,int sum ,int node) { if(Ans < sum) Ans = sum; if(sum + n - node < Ans) return; for(int i = to + 1 ;i <= n ;i ++) if(ok(sum ,i)) { now[sum + 1] = i; DFS(i ,sum + 1 ,node + 1); } } int main () { int i ,j; while(~scanf("%d" ,&n) && n) { for(i = 1 ;i <= n ;i ++) for(j = 1 ;j <= n ;j ++) scanf("%d" ,&map[i][j]); Ans = 0; for(i = 1 ;i <= n ;i ++) { now[1] = i; DFS(i ,1 ,1); } printf("%d " ,Ans); } return 0; }
后来学了dp优化后的 900+
#include<stdio.h> #define N 60 int map[N][N]; int dp[N] ,now[N]; int n ,Ans; void DFS(int x ,int sum) { if(sum > Ans) Ans = sum; int able = 0; int tnow[N]; for(int i = x + 1 ;i <= n ;i ++) { tnow[i] = now[i]; if(now[i]) able ++; } if(able + sum <= Ans) return; for(int i = x + 1 ;i <= n ;i ++) { if(!tnow[i]) continue; if(dp[i] + sum <= Ans) continue; for(int j = x + 1 ;j <= n ;j ++) now[j] = tnow[j] & map[i][j]; DFS(i ,sum + 1); } } int Max_Tuan() { Ans = dp[n] = 1; for(int i = n - 1 ;i >= 1 ;i --) { for(int j = 1 ;j <= n ;j ++) now[j] = map[i][j]; DFS(i ,1); dp[i] = Ans; } return Ans; } int main () { int i ,j; while(~scanf("%d" ,&n) && n) { for(i = 1 ;i <= n ;i ++) for(j = 1 ;j <= n ;j ++) scanf("%d" ,&map[i][j]); printf("%d " ,Max_Tuan()); } return 0; }