电力篱笆

Problem description

农夫约翰已经决定建造电网。他已经把他的农田围成一些奇怪的形状,现在必须找出安放电源的最佳位置。
  对于段电网都必须从电源拉出一条电线。电线可以穿过其他电网或者跨过其他电线。电线能够以任意角度铺设,从电源连接到一段电网的任意一点上(也就是,这段电网的端点上或者在其之间的任意一点上)。这里所说的“一段电网”指的是呈一条线段状的电网,并不是连在一起的几段电网。若几段电网连在一起,那么也要分别给这些电网提供电力。
  已知所有的 F(1 <= F <= 150)段电网的位置(电网总是和坐标轴平行,并且端点的坐标总是整数,0 <= X,Y <= 100)。你的程序要计算连接电源和每段电网所需的电线的最小总长度,还有电源的最佳坐标。

电源的最佳坐标可能在农夫约翰的农田中的任何一个位置,并不一是整数。

Input format

第一行包括 F ——电网的数量。
下面的 F 行每行包括两个 X,Y 对,表示这段电网的两个端点。

Output format

只有一行,输出三个浮点数,相邻两个之间留一个空格。假定你的电脑的输出库会正确地对小数进行四舍五入。
  这三个数是: 电源最佳坐标的 X 值,
  电源最佳坐标的 Y 值,和
  需要的电线的总长度(要最小)。

Algorithm design

Greed Enumeration

Problem analysis

离散程度为0.1 如果强行枚举

对于地图上1000*1000个点穷举

算出其到150条篱笆的距离

到单条篱笆的距离用数学思想 是O(1)的算法

复杂度为O(10^6*150)

发现对于一个区域内的点相差必然不会太大

推论出答案点必然位于较优的整数点附近

可以把所有整数点花费计算出来

Sort之后

取一定数量的点进行寻找答案

因为对于单个点算距离是O(150)

一个整数点可以引申出400个点

所以取了1000个点可以恰好不超时

O(1000*400*150)

将着1000个点引申出的所有小数点进行排序即可

还有一点要注意 在列举点的时候有的点位于同一个矩形内

所以可以加个vit 避免冗余的计算

 

Anyway

对于总体而言,单峰性质还是有的

先取横行三分点,再取纵列三分点

由单调性得出最小值也未尝不是一种方法

O(log3n*log3n*n)

【Source code】

  1 #include <bits/stdc++.h>
  2  
  3 #define F(i,j,k) for(int i=j;i<=k;i++)
  4 #define D(i,j,k) for(int i=j;i>=k;i--)
  5 #define max_cnt 151
  6 #define bnd_map 101
  7  
  8 using namespace std;
  9  
 10 double dx[4]={1,-1,1,-1};
 11 double dy[4]={1,-1,-1,1};
 12 int cnt_fen,cnt_int,vit[bnd_map][bnd_map];
 13 doublex_lea,y_lea,cos_lea,x_ans,y_ans,bnd_fen[max_cnt][2][2],dis_int[bnd_map][bnd_map],poi_map[2];
 14 //bnd_fen「顺序」「始/末」「横/纵」
 15  
 16 struct stud
 17 {
 18    double cos;
 19    double x;
 20    double y;
 21 }cos_int[bnd_map*bnd_map];
 22  
 23 bool cmp(stud p,stud q)
 24 {
 25    if(p.cos!=q.cos)return p.cos<q.cos;
 26    if(p.x!=q.x)return p.x<q.x;
 27    return p.y<q.y;
 28 }//sort排序返回最优点
 29  
 30 double mi(double x)
 31 {
 32    return x*x;
 33 }
 34  
 35 double distance(double sub[])
 36 {
 37    double dis=0;
 38    F(tur,1,cnt_fen)
 39    F(dir,0,1)
 40       if(bnd_fen[tur][0][dir]==bnd_fen[tur][1][dir])
 41       {
 42 if(sub[1-dir]>=bnd_fen[tur][0][1-dir]&&sub[1-dir]<=bnd_fen[tur][1][1-dir])
 43             dis+=abs(bnd_fen[tur][0][dir]-sub[dir]);
 44          else dis+=sqrt(mi(bnd_fen[tur][0][dir]-sub[dir])+min(mi(sub[1-dir]-bnd_fen[tur][0][1-dir]),mi(sub[1-dir]-bnd_fen[tur][1][1-dir])));
 45         break;
 46       }
 47    return dis;
 48 }//函数计算到所有网的距离
 49  
 50 void search(int dir)
 51 {
 52    for(double sub1=0;sub1<=1;sub1+=0.1)
 53    for(double sub2=0;sub2<=1;sub2+=0.1)
 54    {
 55       poi_map[0]=x_lea+dx[dir]*sub1;
 56       poi_map[1]=y_lea+dy[dir]*sub2;
 57       double dis_now=distance(poi_map);
 58       if(dis_now<cos_lea)
 59       {
 60          cos_lea=dis_now;
 61          x_ans=poi_map[0];
 62          y_ans=poi_map[1];
 63       }
 64    }
 65    return;
 66 }//将区域内100个点依次比较
 67  
 68 void input()
 69 {
 70    cin>>cnt_fen;
 71    F(i,1,cnt_fen)
 72    {
 73       F(j,0,1)F(k,0,1)cin>>bnd_fen[i][j][k];
 74       F(k,0,1)
 75       if(bnd_fen[i][0][k]>bnd_fen[i][1][k])
 76          swap(bnd_fen[i][0][k],bnd_fen[i][1][k]);
 77    }
 78    return;
 79 }
 80  
 81 void work_int()
 82 {
 83    for(poi_map[0]=0;poi_map[0]<bnd_map;poi_map[0]++)
 84    for(poi_map[1]=0;poi_map[1]<bnd_map;poi_map[1]++)
 85       dis_int[(int)poi_map[0]][(int)poi_map[1]]=distance(poi_map);
 86    F(i,0,bnd_map-1)
 87    F(j,0,bnd_map-1)
 88    {
 89       cnt_int++;
 90       cos_int[cnt_int].cos=dis_int[i][j];
 91       cos_int[cnt_int].x=(double)i;
 92       cos_int[cnt_int].y=(double)j;
 93    }
 94    sort(cos_int+1,cos_int+cnt_int+1,cmp);
 95    return;
 96 }//算出所有整点花费
 97  
 98 void work_dou()
 99 {
100    cos_lea=cos_int[1].cos;
101    x_ans=cos_int[1].x;
102    y_ans=cos_int[1].y;
103    F(tur,1,min(1000,cnt_int))
104    {
105       x_lea=cos_int[tur].x;
106       y_lea=cos_int[tur].y;
107       vit[(int)x_lea][(int)y_lea]=1;
108       F(i,0,3)
109       {
110 if(x_lea+dx[i]<bnd_map&&x_lea+dx[i]>=0&&y_lea+dy[i]<bnd_map&&y_lea+dy[i]>=0&&!vit[(int)(x_lea+dx[i])][(int)(y_lea+dy[i])])
111          search(i);
112       }
113    }
114    return;
115 }//取前1000个点延伸
116  
117 void output()
118 {
119    printf("%.1lf %.1lf %.1lf\n",x_ans,y_ans,cos_lea);
120    return;
121 }
122  
123 int main()
124 {
125    freopen("fence.in","r",stdin);
126    freopen("fence.out","w",stdout);
127    input();
128    work_int();
129    work_dou();
130    output();
131    return 0;
132 }
133  
贪心
  1 #include <bits/stdc++.h>
  2 #define max_cnt 151
  3 #define bnd_map 101
  4  
  5 using namespace std;
  6  
  7 int dx[4]={1,-1,1,-1}, dy[4]={1,-1,-1,1};
  8 int cnt_fen,vit[bnd_map][bnd_map];
  9 double cos_ans,x_ans,y_ans,bnd_fen[max_cnt][2][2],poi_map[2];
 10 //bnd_fen「顺序」「始/末」「横/纵」
 11  
 12 struct stud
 13 {
 14    double cos;
 15    double x;
 16    double y;
 17 }cos_int[bnd_map*bnd_map];
 18  
 19 double mi(double x)
 20 {
 21    return x*x;
 22 }
 23  
 24 double distance(double sub[])
 25 {
 26    double dis=0;
 27    for(int tur=1;tur<=cnt_fen;tur++)
 28    for(int dir=0;dir<=1;dir++)
 29       if(bnd_fen[tur][0][dir]==bnd_fen[tur][1][dir])
 30       {
 31          if(sub[1-dir]>=bnd_fen[tur][0][1-dir]&&sub[1-dir]<=bnd_fen[tur][1][1-dir])
 32             dis+=abs(bnd_fen[tur][0][dir]-sub[dir]);
 33          else dis+=sqrt(mi(bnd_fen[tur][0][dir]-sub[dir])+min(mi(sub[1-dir]-bnd_fen[tur][0][1-dir]),mi(sub[1-dir]-bnd_fen[tur][1][1-dir])));
 34          break;
 35       }
 36    return dis;
 37 }//函数计算到所有网的距离
 38  
 39 void search_col(double f,double p)
 40 {
 41    double sub[2],dis[2];
 42    sub[0]=(p-f)/3+f,sub[1]=(p-f)*2/3+f;
 43    if(sub[1]-sub[0]<=0.001)
 44    {
 45       poi_map[1]=sub[0];
 46       return;
 47    }
 48    for(int i=0;i<=1;i++)
 49    {
 50       poi_map[1]=sub[i];
 51       dis[i]=distance(poi_map);
 52    }
 53    if(dis[0]<=dis[1])search_col(f,sub[1]);
 54    else search_col(sub[0],p);
 55    return;
 56 }
 57  
 58 void search_row(double f,double p)
 59 {
 60    double sub[2],dis[2];
 61    memset(sub,0,sizeof(sub));
 62    memset(dis,0,sizeof(dis));
 63    sub[0]=(p-f)/3+f,sub[1]=(p-f)*2/3+f;
 64           if(sub[1]-sub[0]<=0.001)
 65    {
 66       poi_map[0]=sub[0];
 67       search_col(0,bnd_map-1);
 68       double dis_now=distance(poi_map);
 69       if(dis_now<cos_ans)
 70       {
 71          cos_ans=dis_now;
 72          x_ans=poi_map[0];
 73          y_ans=poi_map[1];
 74       }
 75       return;
 76    }
 77    for(int i=0;i<=1;i++)
 78    {
 79       poi_map[0]=sub[i];
 80       search_col(0,bnd_map-1);
 81       dis[i]=distance(poi_map);
 82    }//列三分
 83    if(dis[0]<=dis[1])search_row(f,sub[1]);
 84    else search_row(sub[0],p);
 85    return;
 86 }
 87  
 88 void input()
 89 {
 90    cin>>cnt_fen;
 91    for(int i=1;i<=cnt_fen;i++)
 92    {
 93       for(int j=0;j<=1;j++)
 94          for(int k=0;k<=1;k++)
 95             cin>>bnd_fen[i][j][k];
 96       for(int k=0;k<=1;k++)
 97          if(bnd_fen[i][0][k]>bnd_fen[i][1][k])
 98             swap(bnd_fen[i][0][k],bnd_fen[i][1][k]);
 99    }
100    return;
101 }
102  
103 void operate()
104 {
105    x_ans=y_ans=0;
106    poi_map[0]=poi_map[1]=0;
107    cos_ans=distance(poi_map);
108    search_row(0,bnd_map-1);//行三分
109    return ;
110 }
111  
112 void output()
113 {
114    printf("%.1lf %.1lf %.1lf\n",x_ans,y_ans,cos_ans);
115    return;
116 }
117  
118 int main()
119 {
120    freopen("fence.in","r",stdin);
121    freopen("fence.out","w",stdout);
122    input();
123    operate();
124    output();
125    return 0;
126 }
127  
三分

 

over

posted @ 2018-06-08 14:56  Srzer  阅读(301)  评论(0编辑  收藏  举报