题意:在一个网络中有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;
}