蓝桥杯 邮局

历届试题 邮局  
时间限制:1.0s   内存限制:256.0MB
   
锦囊1
锦囊2
锦囊3
问题描述
  C村住着n户村民,由于交通闭塞,C村的村民只能通过信件与外界交流。为了方便村民们发信,C村打算在C村建设k个邮局,这样每户村民可以去离自己家最近的邮局发信。

  现在给出了m个备选的邮局,请从中选出k个来,使得村民到自己家最近的邮局的距离和最小。其中两点之间的距离定义为两点之间的直线距离。
输入格式
  输入的第一行包含三个整数n, m, k,分别表示村民的户数、备选的邮局数和要建的邮局数。
  接下来n行,每行两个整数x, y,依次表示每户村民家的坐标。
  接下来m行,每行包含两个整数x, y,依次表示每个备选邮局的坐标。
  在输入中,村民和村民、村民和邮局、邮局和邮局的坐标可能相同,但你应把它们看成不同的村民或邮局。
输出格式
  输出一行,包含k个整数,从小到大依次表示你选择的备选邮局编号。(备选邮局按输入顺序由1到m编号)
样例输入
5 4 2
0 0
2 0
3 1
3 3
1 1
0 1
1 0
2 1
3 2
样例输出
2 4
数据规模和约定
  对于30%的数据,1<=n<=10,1<=m<=10,1<=k<=5;
  对于60%的数据,1<=m<=20;
  对于100%的数据,1<=n<=50,1<=m<=25,1<=k<=10。

题目如上:
一开始看到这题目,感觉挺复杂的。但静下心来理一理 ,其实也就是深搜,再一个一个比较,只是比较麻烦了点。大概思路是,开一个数组存储村民的坐标,一个数组存储邮局的坐标,再开一个整数数组存储你选择的邮局的标号。深搜选择k个邮局,计算出每个村民到距离他最近的邮局的距离之和,再和之前得到的对比,深搜完所有k个邮局的组合后,我们就可以得到能够使得村民们到最近邮局的距离之和最小的邮局组合。

代码如下:
import java.util.Scanner;
public class Main {
class Point1{
 int x,y;
 public Point1(int n,int m) {
  // TODO Auto-generated constructor stub
  x=n;
  y=m;
 }
}
 static Point1[] people;
 static Point1[] post;
 static Point1[] temp;
 static int[] vis;
 static int[] posttemp;
 static int m;
 static int k;
 static int n;
 static double minresult=10000;
 static int[] postreslt;
 public static void main(String[] args) {
  Main test=new Main();
  Scanner cin=new Scanner(System.in);
  n=cin.nextInt();
  m=cin.nextInt();
  vis=new int[m];
  k=cin.nextInt();
  postreslt=new int[k];
  people=new Point1[n];
  post=new Point1[m];
  posttemp=new int[k];
  temp=new Point1[k];
  for(int i=0;i<n;i++) {
   people[i]=test.new Point1(cin.nextInt(), cin.nextInt());
  }
  for(int i=0;i<m;i++) {
   post[i]=test.new Point1(cin.nextInt(), cin.nextInt());
  }
  dfs(0);
  for(int i=0;i<k;i++) {
   System.out.print((postreslt[i]+1)+" ");
  }
  //System.out.println(minresult);
 }
 private static void dfs(int no) {
  if (no==k) {
   double min;
   int sum=0;
   for(int j=0;j<n;j++) {
    min=1000;
    for(int l=0;l<k;l++) {
     if (getdistance(people[j], post[posttemp[l]])<min) {
      min=getdistance(people[j], post[posttemp[l]]);
     }
    }
    sum+=min;
   }
   if(sum<minresult) {
    minresult=sum;
    for(int i=0;i<k;i++) {
     postreslt[i]=posttemp[i];
    }
   }
   return;
  }
  // TODO Auto-generated method stub
  for(int i=0;i<m;i++) {
   if (vis[i]==0) {
    posttemp[no]=i;
    vis[i]=1;
    dfs(no+1);
    vis[i]=0;
   }
  }
  
 }
 public static double getdistance(Point1 p1,Point1 p2) {
  return Math.sqrt(Math.abs(p1.x-p2.x)*Math.abs(p1.x-p2.x)+Math.abs(p1.y-p2.y)*Math.abs(p1.y-p2.y));
 }
}

接触acm已经大半年了,有时会感觉学得很累。相对与其他应用开发来说,acm可能是成本高,收益不明显的,但是,这练得都是内功,效果不会一下子出来,但是日积月累,思维方式一定会得到很好的锻炼。而且acm的很多题目都可以很好地应用于生活中。所以,加油吧~
后天要参加蓝桥杯比赛了,立个flag,祝自己一切如愿,生活如此美好~~~

发布了14 篇原创文章 · 获赞 2 · 访问量 5388

猜你喜欢

转载自blog.csdn.net/Wolf_South/article/details/79748538