一个王国有 个城市,每个城市有坐标 和海拔 ,在 个城市之间修水渠,要保证每个城市有水,水渠是水平的,每个城市的海拔不同,现在要求修单位长度的水渠的海拔高度差最小。
链接
题解
最优比率生成树,01 分数规划,搞的不是很明白 …… Orz
PS:果然我的代码自带大常数,搞了一早上不是 WA 就是 TLE,最后把编译器从 G++ 改为 VC++ 就 AC 了 ……
代码
#include <cstdio>
#include <cmath>
#include <algorithm>
const int MAXN = 1000;
const int CACHE_FIX = 3;
const float EPS = 1e-4;
struct Node;
struct UndirectedEdge;
struct Node {
int id;
int x, y, z;
bool inTree;
UndirectedEdge *e;
} nodes[MAXN];
struct UndirectedEdge {
float benifit, cost;
float w;
UndirectedEdge(float benifit, float cost) : benifit(benifit), cost(cost) {}
UndirectedEdge() {}
} edges[MAXN + CACHE_FIX][MAXN];
int n;
inline float prim() {
nodes[0].inTree = true;
for (int i = 1; i < n; i++) nodes[i].e = &edges[0][i], nodes[i].inTree = false;
float ans = 0;
for (int i = 0; i < n - 1; i++) {
Node *v = NULL;
for (int i = 0; i < n; i++) if (!nodes[i].inTree && (v == NULL || nodes[i].e->w < v->e->w)) v = &nodes[i];
ans += v->e->w;
v->e = NULL;
v->inTree = true;
for (int i = 0; i < n; i++) if (!nodes[i].inTree && nodes[i].e->w > edges[i][v->id].w) nodes[i].e = &edges[i][v->id];
}
return ans;
}
inline float test(float p) {
for (register int i = 0; i < n; i++) {
for (register int j = i + 1; j < n; j++) {
edges[j][i].w = edges[i][j].w = edges[i][j].cost - edges[i][j].benifit * p;
}
}
float result = prim();
//printf("test(%lf) = %lf\n", p, result);
return result;
}
inline float solve(float sum) {
register float l = 0, r = sum;
//while (r - l > EPS) {
for (int i = 0; i < 22; i++) {
float mid = l + (r - l) / 2;
if (test(mid) > 0) l = mid;
else r = mid;
}
return l + (r - l) / 2;
}
inline float sqr(float x) {
return x * x;
}
inline float distance(float x1, float x2, float y1, float y2) {
return sqrt(sqr(x1 - x2) + sqr(y1 - y2));
}
int main() {
while (scanf("%d", &n) != EOF && n != 0) {
for (int i = 0; i < n; i++) nodes[i].id = i;
for (int i = 0; i < n; i++) scanf("%d %d %d", &nodes[i].x, &nodes[i].y, &nodes[i].z);
float sum = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
edges[j][i] = edges[i][j] = UndirectedEdge(distance(nodes[i].x, nodes[j].x, nodes[i].y, nodes[j].y), abs(nodes[i].z - nodes[j].z));
sum += edges[i][j].benifit;
}
}
float ans = solve(100);
printf("%.3f\n", ans);
}
return 0;
}
数据生成器
#include <cstdio>
#include <cstdlib>
#include <ctime>
const int MAXN = 1000;
inline int luckyRand(int l, int r) {
const int MAGIC_NUMBER = 20000528;
const int x = rand();
srand(x ^ ((time(NULL) << 16) | (clock() << 16 >> 16)) ^ MAGIC_NUMBER);
return (rand() ^ x ^ MAGIC_NUMBER) % (r - l + 1) + l;
}
int main() {
const int t = 3;
const int n = MAXN;
for (int i = 0; i < t; i++) {
printf("%d\n", n);
for (int i = 0; i < n; i++) {
int x = luckyRand(luckyRand(0, 30), luckyRand(30, 60)), y = luckyRand(luckyRand(0, 30), luckyRand(30, 60)), z = luckyRand(luckyRand(0, 10000), luckyRand(90000, 100000));
printf("%d %d %d\n", x, y, z);
}
}
puts("0");
return 0;
}