我之前也没有搞过01规划,但是之前做过3621,3621这道题也用到了01规划,虽然我还是不太理解01规划,但是3621题解的推导过程给了我启示……
- ∑cost[i]/∑len[i] <= ans
- ∑cost[i] <= ans * ∑len[i]
- ∑(cost[i] - ans * len[i]) <= 0
当和小于0时说明ans需变小
还有这一题目很自然就要用prim,题目只给了点的坐标和高度,而且点也不算太多,如果用Krustral要存的边会很多……而且第一个城市是首都,(there will be only one way to connect each village to the capital),从第一个点开始就很自然了……而且3621很坑爹的输出让我WA了N次,还是参考别人的代码改成%.2f的,才A,这一题很自然就只用%.3f了,可是这为什么啊?
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 5 const int maxN = 1000+10; 6 const double eps = 1e-6; 7 int n; 8 int x[maxN],y[maxN],h[maxN]; 9 double dist[maxN][maxN]; 10 int height[maxN][maxN]; 11 double d[maxN]; 12 bool vis[maxN]; 13 14 double dis(int i,int j) 15 { 16 return sqrt(1.0*(x[i] - x[j])*(x[i] - x[j]) + 1.0 * (y[i] - y[j]) * (y[i] - y[j])); 17 } 18 19 int heig(int i,int j) 20 { 21 int ans = h[i] - h[j]; 22 return ans < 0?(-ans):ans; 23 } 24 25 double prim(double mid) 26 { 27 memset(vis,false,sizeof(vis)); 28 for(int i = 0;i < n;i ++) 29 { 30 d[i] = height[0][i] - mid*dist[0][i]; 31 } 32 vis[0] = true; 33 double sum = 0; 34 for(int i = 1;i < n;i ++) 35 { 36 double minn = 1000000000+1000000; 37 int k = 0; 38 for(int j = 1;j < n;j ++) 39 { 40 if(!vis[j] && minn > d[j]) 41 { 42 minn = d[k = j]; 43 } 44 } 45 46 sum += minn; 47 vis[k] = true; 48 for(int j = 1;j < n;j ++) 49 { 50 double jj = height[k][j] - mid*dist[k][j]; 51 if(!vis[j] && d[j] > jj) 52 { 53 d[j] = jj; 54 } 55 } 56 } 57 58 return sum; 59 } 60 61 int main() 62 { 63 while(scanf("%d",&n),n) 64 { 65 for(int i = 0;i < n;i ++) 66 { 67 scanf("%d%d%d",&x[i],&y[i],&h[i]); 68 } 69 70 for(int i = 0;i < n-1;i ++) 71 { 72 dist[i][i] = 0; 73 height[i][i] = 0; 74 for(int j = i + 1;j < n;j ++) 75 { 76 dist[i][j] = dist[j][i] = dis(i,j); 77 height[i][j] = height[j][i] = heig(i,j); 78 } 79 } 80 dist[n-1][n-1] = 0; 81 height[n-1][n-1] = 0; 82 83 double left = 0; 84 double right = 100000; 85 while(right - left > eps) 86 { 87 double mid = (left + right) / 2; 88 if(prim(mid) < 0) 89 { 90 right = mid; 91 } 92 else 93 { 94 left = mid; 95 } 96 } 97 98 printf("%.3f\n",left); 99 } 100 101 return 0; 102 }