样例输出:
3
2 3
3
10
1 3 2
8
5 7 2 14 17 11 13
18 13 4 3 14 5
14 3 10 3 5
19 0 9 4
5 15 6
19 12
16
622
3 7 8 6 5 2 4 1
代码:
#include<iostream>
using namespace std;
int t[21][21];//记录两个部件的连线数
int n;
int Min = 10000000;
bool used[21];//记录该位置是否被放过
int record[21];//记录每一次结果:第i个部件放在record[i]个位置上(题意表达不清,建议看本文文末链接文章里的评论)
int minRecord[21];
int whenAdd(int x) {//新放一个元件时,计算新加的成本
int sum = 0;
int now = record[x];//x部件的位置
for (int i = 1; i < x; i++) {//前x个部件已经放过了
int from = record[i];
int dis = now - from;
dis = dis > 0 ? dis : (-dis);
sum += dis * t[x][i];
}
return sum;
}
void f(int x,int sum) {//第x个元件
if (x == n+1) {
if (sum < Min) {
Min = sum;
for (int i = 1; i <= n; i++) {
minRecord[i] = record[i];
}
}
return;
}
for (int i = 1; i <= n; i++) {
if (!used[i])//第i个位置若没放过
{
record[x] = i;//第x个原件放在第i个位置上
int temp = whenAdd(x);
sum +=temp;
if (sum < Min) {
used[i] = true;
f(x + 1, sum);
}
used[i] = false;
record[x] = 0;
sum -= temp;
}
}
}
int main() {
cin >> n;
for (int i = 1; i < n; i++) {
for (int j = i + 1; j <= n; j++) {
cin >> t[i][j];
t[j][i] = t[i][j];//部件i到j的连接数和部件j到i的连接数一样
}
used[i] = false;
}
f(1, 0);
cout << Min<<endl;
for (int i = 1; i <= n; i++) {
cout << minRecord[i] << " ";
}
}
欢迎留言更优雅的解法。
问题描述参考: 算法设计与分析: 5-16 布线问题