zoukankan      html  css  js  c++  java
  • 电力篱笆

    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

  • 相关阅读:
    BZOJ4849[Neerc2016]Mole Tunnels——模拟费用流+树形DP
    BZOJ3638[Codeforces280D]k-Maximum Subsequence Sum&BZOJ3272Zgg吃东西&BZOJ3267KC采花——模拟费用流+线段树
    BZOJ3291Alice与能源计划——匈牙利算法+模拟费用流
    BZOJ2151种树——模拟费用流+链表+堆
    CF1117D Magic Gems
    CF1117C Magic Ship
    CF1117A Best Subsegment
    Loj 2028 随机序列
    Loj 504 ZQC的手办
    Luogu 3806 点分治1
  • 原文地址:https://www.cnblogs.com/qswx/p/9155679.html
Copyright © 2011-2022 走看看