因为是完全图,所以可以采用如下的方式进行DFS搜索,枚举出每一种情况,然后用Prim进行计算。
#include<cstdio>
#include<cstring>
#define N 20
int n,m,vis[N], ans[N], pre[N], hash[N];
double G[N][N], weight[N], minCost[N], minRatio;
double prim(){
memset(hash, 0, sizeof(hash));
int u;
for(int i=1; i<=n; ++i)if(vis[i]){
u=i; break;
}
hash[u] = 1;
double weightSum=0, edgeSum=0;
for(int i=1; i<=n; ++i)if(vis[i]){
minCost[i] = G[u][i]; pre[i] = u;
weightSum += weight[i];
}
for(int i=1; i<m; ++i){
u=-1;
for(int j=1; j<=n; ++j)if(vis[j]&&!hash[j]){
if(u==-1 || minCost[u]>minCost[j])
u=j;
}
edgeSum += G[pre[u]][u];
hash[u] = 1;
for(int j=1; j<=n; ++j)if(vis[j]&&!hash[j]){
if(minCost[j] > G[u][j]){
minCost[j] = G[u][j];
pre[j] = u;
}
}
}
return edgeSum/weightSum;
}
void dfs(int u, int num){
if(num>m) return;
if(u==n+1){
if(num!=m) return;
double t=prim();
if(t<minRatio){
minRatio = t;
memcpy(ans, vis, sizeof(vis));
}
return;
}
vis[u] = 1;
dfs(u+1, num+1);
vis[u] = 0;
dfs(u+1, num);
}
int main(){
while(~scanf("%d%d",&n,&m)){
if(!n&&!m) break;
for(int i=1; i<=n; ++i)
scanf("%lf",&weight[i]);
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
scanf("%lf",&G[i][j]);
memset(vis, 0, sizeof(vis));
minRatio = 100000000;
dfs(1, 0);
bool flag=false;
for(int i=1; i<=n; ++i)if(ans[i]){
if(flag) printf(" %d", i);
else { printf("%d",i); flag=true; }
}
puts("");
}
return 0;
}

本文介绍了一种在完全图中使用深度优先搜索(DFS)来枚举所有可能情况,并利用Prim算法计算最小生成树平均权重的方法。通过具体代码实现展示了如何找到最优解。
323

被折叠的 条评论
为什么被折叠?



