Shirlies
宁静专注认真的程序媛~

我之前也没有搞过01规划,但是之前做过3621,3621这道题也用到了01规划,虽然我还是不太理解01规划,但是3621题解的推导过程给了我启示……

  1. ∑cost[i]/∑len[i] <= ans
  2. ∑cost[i] <= ans * ∑len[i]
  3. ∑(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 }

 

 

 

posted on 2012-08-30 12:43  Shirlies  阅读(181)  评论(0编辑  收藏  举报