这题好题啊,网上也有很多解题报告的呢,哥也是看了才懂写的。。
直接贴代码。这个代码不咋地呢。
分数规划用迭代法500+ms,用二分法就2000+ms了。可见差异还是挺大的,还是迭代法好。
膜拜下分数规划算法的创始人
#include <stdio.h>
#include <math.h>
#include <string.h>
int X[1024], Y[1024], Z[1024], N, from[1024];
char mst[1024];
double D[1024], rate;
struct {
double w, cost, len;
} E[1024][1024];
double prim(double L)
{
int i, j;
double res, cost, len;
for (i = 0; i < N; i++)
for (j = i; j < N; j++)
E[i][j].w = E[j][i].w = E[i][j].cost - E[i][j].len * L;
for (i = 0; i < N; i++) {
D[i] = E[0][i].w;
from[i] = 0;
}
memset(mst, 0, N);
mst[0] = 1;
res = cost = len = 0;
for (i = 0; i < N - 1; i++) {
double min_d;
int min_i;
min_d = 1e50;
for (j = 0; j < N; j++) {
if (!mst[j] && D[j] < min_d) {
min_d = D[j];
min_i = j;
}
}
mst[min_i] = 1;
res += min_d;
cost += E[min_i][from[min_i]].cost;
len += E[min_i][from[min_i]].len;
for (j = 0; j < N; j++) {
if (!mst[j] && E[min_i][j].w < D[j]) {
D[j] = E[min_i][j].w;
from[j] = min_i;
}
}
}
rate = cost / len;
return res;
}
void solve()
{
/**//*
double l, r, m;
l = 0;
r = 1000;
while (r - l > 0.0001) {
m = (r + l) / 2;
if (prim(m) > 0)
l = m;
else
r = m;
}
*/
double r;
int i, j;
for (i = 0; i < N; i++) {
for (j = i; j < N; j++) {
double dx, dy;
dx = (double)X[i] - X[j];
dy = (double)Y[i] - Y[j];
E[i][j].cost = E[j][i].cost = fabs((double)Z[i] - Z[j]);
E[i][j].len = E[j][i].len = sqrt(dx*dx + dy*dy);
}
}
rate = 0;
do {
r = rate;
prim(rate);
} while (fabs(r - rate) > 0.0001);
printf("%.3f\n", rate);
}
int main()
{
int i;
freopen("e:\\test\\in.txt", "r", stdin);
while (1) {
scanf("%d", &N);
if (!N)
break;
for (i = 0; i < N; i++)
scanf("%d%d%d", &X[i], &Y[i], &Z[i]);
solve();
}
return 0;
}