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 ",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 ",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