[HDU5046] Airport

本文介绍了一种通过二分查找与舞蹈链算法结合的方法来解决在一个由多个城市组成的国家中选择若干城市建立机场的问题,目的是使得任意城市的居民到最近机场的距离最大化地最小。通过具体的代码实现展示了如何求解这一问题。
摘要由CSDN通过智能技术生成
Description
The country of jiuye composed by N cites. Each city can be viewed as a point in a two- dimensional plane with integer coordinates (x,y). The distance between city i and city j is defined by d ij = |x i - x j| + |y i - y j|. jiuye want to setup airport in K cities among N cities. So he need your help to choose these K cities, to minimize the maximum distance to the nearest airport of each city. That is , if we define d i(1 ≤ i ≤ N ) as the distance from city i to the nearest city with airport. Your aim is to minimize the value max{d i|1 ≤ i ≤ N }. You just output the minimum.
Input
The first line of the input is T (1 ≤ T ≤ 100), which stands for the number of test cases you need to solve.
The first line of each case contains two integers N ,K (1 ≤ N ≤ 60,1 ≤ K ≤ N ),as mentioned above.
The next N lines, each lines contains two integer x i and y i (-10 9 ≤ x i, y i ≤ 10 9), denote the coordinates of city i.
Output
For each test case, print a line “Case #t: ”(without quotes, t means the index of the test case) at the beginning. Then a single integer means the minimum.
Sample Input
2
3 2
0 0
4 0
5 1
4 2
0 3
1 0
3 0
8 9
Sample Output
Case #1: 2
Case #2: 4
首先二分最大距离,对于每个距离采用舞蹈链算法判断其是否满足要求
代码如下
 1 #include<bits/stdc++.h>
 2 #define FOR(i,p,X) for(int i=X[p];i!=p;i=X[i])
 3 #define For(i,a,b) for(int i=(a),i_end=(b);i<=i_end;++i)
 4 using namespace std;
 5 const int N=70;
 6 int n,m,ans;
 7 vector<int>G[N];
 8 struct DLX{  
 9     int L[N*N],R[N*N],U[N*N],D[N*N];
10     int C[N*N],H[N],cnt[N],vis[N],id;
11     void init(){  
12         For(i,0,n){  
13             cnt[i]=0;U[i]=D[i]=i;  
14             L[i+1]=i;R[i]=i+1;  
15         }  
16         R[n]=0;id=n+1;  
17         memset(H,-1,sizeof(H));  
18     }  
19     void Link(int r,int c){  
20         cnt[c]++;C[id]=c;  
21         U[id]=U[c];D[U[c]]=id;  
22         D[id]=c;U[c]=id;  
23         if(!~H[r]) H[r]=L[id]=R[id]=id;  
24         else{  
25             L[id]=L[H[r]];R[L[H[r]]]=id;  
26             R[id]=H[r];L[H[r]]=id;  
27         }  
28         id++;  
29     }
30     void Remove(int sz){
31         FOR(j,sz,D)L[R[j]]=L[j],R[L[j]]=R[j];  
32     }  
33     void Resume(int sz){  
34         FOR(j,sz,D)L[R[j]]=R[L[j]]=j;  
35     } 
36     int h(){  
37         int res=0;  
38         memset(vis,0,sizeof(vis));  
39         FOR(i,0,R){
40             if(vis[i])continue;  
41             ++res;  
42             FOR(j,i,D)FOR(k,j,R)
43                 vis[C[k]]=1;
44         }
45         return res;  
46     }  
47     bool Dance(int k){  
48         if(k+h()>m)return false;  
49         int pos=R[0];
50         if(!pos)return k<=m;
51         FOR(i,0,R)if(cnt[pos]>cnt[i])pos=i; 
52         FOR(i,pos,D){
53             Remove(i);
54             FOR(j,i,R)Remove(j);  
55             if(Dance(k+1))return true;  
56             FOR(j,i,R)Resume(j);  
57             Resume(i);  
58         }
59         return false;
60     }
61 }dlx;
62 struct Point{
63     int x,y;
64     void input(){
65         scanf("%d%d",&x,&y);
66     }
67 }city[N];
68 long long dis(Point a,Point b){
69     return (long long)abs(a.x-b.x)+(long long)abs(a.y-b.y);
70 }
71 int main(){
72     int T;
73     scanf("%d",&T);
74     For(iCase,1,T){
75         scanf("%d%d",&n,&m);
76         For(i,1,n)city[i].input();
77         long long l=0,r=100000000000LL;
78         long long ans=0;
79         while(l<=r){
80             long long mid=l+r>>1;
81             dlx.init();
82             For(i,1,n)For(j,1,n)
83                 if(dis(city[i],city[j])<=mid)
84                     dlx.Link(i,j);
85             if(dlx.Dance(0))r=(ans=mid)-1;
86             else l=mid+1;
87         }
88         printf("Case #%d: %I64d\n",iCase,ans);
89     }
90     return 0;
91 }

 

转载于:https://www.cnblogs.com/ndqzhang1111/p/7172126.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值