2728

1 /*
2 此题和3757一样都用到了分数规划。
3 做了这两个题之后,感觉这样的问题一般是找个比率的最小值,
4 然后转化为目标函数的形式,然后在通过某种方法或者排序或者最小生成树
5 等等来找最小的解
6
7
8 任何两点之间都可连线,然后找出一个最小生成树
9 01二分规划
10 最优比率生成树
11 二分
12 迭代
13 Dinkelbach算法
14
15 sigma(cost[i])/sigma(len[i]) >= lamda
16
17 L = sigma(cost[i]) - lamda*sigma(len[i]). 01分数规划,可二分解和dinkelbach算法迭代解
18 */
19
20 // include file
21 #include <cstdio>
22 #include <cstdlib>
23 #include <cstring>
24 #include <cmath>
25 #include <cctype>
26 #include <ctime>
27
28 #include <iostream>
29 #include <sstream>
30 #include <fstream>
31 #include <iomanip>
32 #include <bitset>
33 #include <strstream>
34
35 #include <algorithm>
36 #include <string>
37 #include <vector>
38 #include <queue>
39 #include <set>
40 #include <list>
41 #include <functional>
42
43 using namespace std;
44
45 // typedef
46 typedef long long LL;
47 typedef unsigned long long ULL;
48
49 //
50 #define read freopen("in.txt","r",stdin)
51 #define write freopen("out.txt","w",stdout)
52 #define FORi(a,b,c) for(int i=(a);i<(b);i+=c)
53 #define FORj(a,b,c) for(int j=(a);j<(b);j+=c)
54
55 #define FF(i,a) for(int i=0;i<(a);i+++)
56 #define FFD(i,a) for(int i=(a)-1;i>=0;i--)
57 #define Z(a) (a<<1)
58 #define Y(a) (a>>1)
59
60 const double eps = 1e-6;
61 const double INF = 1e10;
62 const double Pi = acos(-1.0);
63
64 template<class T> inline T sqr(T a){return a*a;}
65 template<class T> inline T TMAX(T x,T y)
66 {
67 if(x>y) return x;
68 return y;
69 }
70 template<class T> inline T TMIN(T x,T y)
71 {
72 if(x<y) return x;
73 return y;
74 }
75 template<class T> inline void SWAP(T &x,T &y)
76 {
77 T t = x;
78 x = y;
79 y = t;
80 }
81 template<class T> inline T MMAX(T x,T y,T z)
82 {
83 return TMAX(TMAX(x,y),z);
84 }
85
86
87 // code begin
88 #define MAXN 1100
89
90 int N;
91 struct node
92 {
93 double x;
94 double y;
95 double z;
96 };
97 node G[MAXN];
98 double dst[MAXN];
99 bool used[MAXN];
100 int pre[MAXN];
101
102 double Dis(int a,int b)
103 {
104 return sqrt( (G[a].x-G[b].x)*(G[a].x-G[b].x)+(G[a].y-G[b].y)*(G[a].y-G[b].y) );
105 }
106
107 double MST_prim(double lamda)
108 {
109 //从节点0开始mst
110 memset(used,0,sizeof(used));
111 memset(dst,0,sizeof(dst));
112 FORi(1,N,1)
113 {
114 dst[i] = fabs( G[i].z-G[0].z ) - lamda*Dis(i,0) ;
115 pre[i] = 0;
116 }
117 dst[0] = 0;
118 used[0] = 1;
119 pre[0] = -1;
120
121 double cost= 0,len = 0;
122 FORi(1,N,1)
123 {
124 //找出最小的值,和索引
125 double mind = INF;
126 int k = -1;
127 FORj(0,N,1)
128 {
129 if(!used[j] && dst[j]<mind)
130 {
131 mind = dst[j];
132 k = j;
133 }
134 }
135 cost += fabs( G[k].z-G[pre[k]].z );
136 len += Dis( k,pre[k] );
137 if(k!=-1)
138 {
139 used[k] = true;
140 FORj(0,N,1)
141 {
142 if(!used[j] && ( fabs(G[k].z-G[j].z)-lamda*Dis(k,j) )<dst[j] )
143 {
144 dst[j] = fabs(G[k].z-G[j].z)-lamda*Dis(k,j);
145 pre[j] = k;
146 }
147 }
148 }
149 }
150 return cost/len;
151 }
152
153 int main()
154 {
155 read;
156 write;
157 while(scanf("%d",&N)!=-1)
158 {
159 if(N==0) break;
160 FORi(0,N,1)
161 {
162 scanf("%lf %lf %lf",&G[i].x,&G[i].y,&G[i].z);
163 }
164
165 double a=0,b;
166 while(true)
167 {
168 b = MST_prim(a);
169 if(fabs(a-b)<eps) break;
170 a = b;
171 }
172 printf("%.3f\n",a);
173 }
174 return 0;
175 }
posted @ 2011-03-02 19:37  AC2012  阅读(293)  评论(0编辑  收藏  举报