題意:在一個網路中有n個節點,現在需要把n個節點分成兩部分,每部分之間的通訊代價為0,不同部分之間的通訊代價為Cij。求一種劃分方式,是的總得代價最大。
題解:dfs, 隨機化演算法都可以。下面給出了兩種dfs的實現方法。
方法一:dfs
#include <iostream>using namespace std;int map[22][22], check[22];int n, ans;void dfs ( int k, int sum ){if ( k > n ){ans = sum > ans ? sum : ans;return;}int i, temp;check[k] = 1; temp = 0;for ( i = 1; i < k; i++ ){if ( check[i] != check[k] ) temp += map[i][k];}dfs ( k + 1, sum + temp );check[k] = 0; temp = 0;for ( i = 1; i < k; i++ ){if ( check[i] != check[k] )temp += map[i][k];}dfs ( k + 1, sum + temp );}int main(){while ( scanf("%d",&n) != EOF ){memset(check,0,sizeof(check));for ( int i = 1; i <= n; i++ )for ( int j = 1; j <= n; j++ )scanf("%d",&map[i][j]);ans = 0;dfs ( 1, 0 );printf("%d\n",ans);}return 0;}
#include <iostream>using namespace std;int map[22][22], A[22], B[22]; /* A, B 兩部分 */int n, ans;void dfs ( int k, int sum, int sizeA, int sizeB ){if ( k > n ){ans = sum > ans ? sum : ans;return;}int i, temp;A[sizeA+1] = k; temp = 0;for ( i = 1; i <= sizeB; i++ )temp += map[B[i]][k];dfs ( k + 1, sum + temp, sizeA + 1, sizeB );B[sizeB+1] = k; temp = 0;for ( i = 1; i <= sizeA; i++ )temp += map[A[i]][k];dfs ( k + 1, sum + temp, sizeA, sizeB + 1 );}int main(){while ( scanf("%d",&n) != EOF ){memset(A,0,sizeof(A));memset(B,0,sizeof(B));for ( int i = 1; i <= n; i++ )for ( int j = 1; j <= n; j++ )scanf("%d",&map[i][j]);ans = 0;A[1] = 1;dfs ( 2, 0, 1, 0 );printf("%d\n",ans);}return 0;}
方法二:隨機化演算法
#include <ctime>#include <iostream>using namespace std;int map[22][22], group[22];int main(){int cnt, n, ans, sum, i, j, k;while ( scanf("%d",&n) != EOF ){for ( i = 1; i <= n; i++ )for ( j = 1; j <= n; j++ )scanf("%d",&map[i][j]);cnt = 200000;sum = ans = 0;memset(group,0,sizeof(group));while ( cnt-- ){k = rand() % n + 1;group[k] = ! group[k];for ( i = 1; i <= n; i++ ){if ( group[i] && group[k] ) sum -= map[i][k];if ( group[i] && !group[k] ) sum += map[i][k];if ( !group[i] && group[k] ) sum += map[i][k];if ( !group[i] && !group[k] ) sum -= map[i][k];}ans = sum > ans ? sum : ans;}printf("%d\n",ans);}return 0;}