剪枝策略:
初始设置所有节点都归于集合A,如果将某元素由集合A移动到集合B,流量会减小,则剪枝
因为在递归过程中,集合A中元素越来越多,diff值是单调递减的,因此当diff为负时,后续的sum只会减小
#include <iostream>
using namespace std;
const int MAX_NUM = 24;
const int A = 0;
const int B = 1;
int C[MAX_NUM][MAX_NUM];
int set[MAX_NUM]; //记录某元素属于哪个集合
int n;
int max_val = 0;
void dfs(int k, int sum)
{
if (k == n){
max_val = sum > max_val ? sum : max_val;
return;
}
int i, diff = 0;
for (i = 1; i <= n; ++i){ //元素由集合A移动到集合B,流量变化情况
if (set[i] == B){
diff -= C[i][k];
}
else{
diff += C[i][k];
}
}
//如果将该元素由集合A移动到集合B,流量会减小,则剪枝
//因为在递归过程中,集合A中元素越来越多,diff值是单调递减的,因此当diff为负时,后续的sum只会减小
if (diff > 0){
set[k] = B;
dfs(k+1, sum+diff);
}
set[k] = A;
dfs(k+1, sum);
}
int main()
{
while(scanf("%d", &n) != EOF){
memset(set, 0, sizeof(set));
max_val = 0;
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= n; ++j){
scanf("%d", &C[i][j]);
}
}
dfs(1, 0);
printf("%d\n", max_val);
}
return 0;
}