題意就是把節點分成A、B兩組,節點間距C給了,要求解分組的方法,使得∑Cij (i∈A,j∈B)最大。
首先把所有節點都放在一組,然后采用深度優先搜索的方法,對每一個節點都做判斷是否應該移到另一組去,判斷的依據是移過去和不移過去哪個得到的和值比較大(這里移去B組后的計算方法就是加上該點和在A組中的所有點的間距,和減去原本就在B組中的所有點的間距),如果移過去變小了,那么則不移過去,並剪掉該條支路。
DFS的本質就是枚舉,一種遞歸的枚舉。比如如果這個程序里面不剪枝的話就可以枚舉到所有的分組情況。剪枝是優化的方法,對滿足一定條件的做出判斷,認為枚舉下去已經沒有意義,所以剪掉其分支。
#include <iostream> using namespace std; const int MAX_N = 20; int n; int map[MAX_N + 1][MAX_N + 1]; bool in_group[MAX_N + 1]; int ans; void dfs(int id, int cur_sum) { in_group[id] = true; int tmp_sum = cur_sum; for (int i = 1; i <= n; i++){ if (in_group[i]){ tmp_sum -= map[id][i]; } else{ tmp_sum += map[id][i]; } } if (tmp_sum > ans){ ans = tmp_sum; } if (tmp_sum > cur_sum){ for (int i = id + 1; i <= n; i++){ dfs(i, tmp_sum); } } in_group[id] = false; } int main() { cin >> n; memset(in_group, 0, sizeof(in_group)); ans = 0; for (int i = 1; i <= n; i++){ for (int j = 1; j <= n; j++){ cin >> map[i][j]; } } dfs(1, 0); cout << ans << endl; return 0; }