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 di(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.
InputThe 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.OutputFor 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
题意:有n块小岛,现在要在其中的k块小岛上建立飞机场,给出小岛的坐标,其中小岛之间的距离d(i,j)=|xi-xj|+|yi-yj|;求建立k个飞机时,飞机的最小航距时多少;
思路:二分法判断航距,用DLX重复覆盖判断当前航距下能否满足k座,最后一步步缩小答案。注意岛之间的距离非常大,用long long 存放。
代码:
1 #include <cstdio> 2 #include <fstream> 3 #include <algorithm> 4 #include <cmath> 5 #include <deque> 6 #include <vector> 7 #include <queue> 8 #include <string> 9 #include <cstring> 10 #include <map> 11 #include <stack> 12 #include <set> 13 #include <sstream> 14 #include <iostream> 15 #define mod 998244353 16 #define eps 1e-6 17 #define ll long long 18 #define INF 0x3f3f3f3f 19 using namespace std; 20 21 const int maxn=4010; 22 int k; 23 struct 24 { 25 int left[maxn],right[maxn],up[maxn],down[maxn]; 26 int head[65],col[maxn]; 27 int num[65],id; 28 void init(int m) 29 { 30 for(int i=0;i<=m;i++) 31 { 32 left[i]=i-1; 33 right[i]=i+1; 34 up[i]=down[i]=i; 35 col[i]=i; 36 } 37 id=m; 38 left[0]=m; 39 right[m]=0; 40 memset(head,-1,sizeof(head)); 41 memset(num,0,sizeof(num)); 42 } 43 void link(int x,int y) 44 { 45 id++; 46 down[id]=down[y]; 47 up[down[y]]=id; 48 up[id]=y; 49 down[y]=id; 50 num[y]++; 51 col[id]=y; 52 if(head[x]==-1) 53 { 54 head[x]=left[id]=right[id]=id; 55 } 56 else 57 { 58 right[id]=right[head[x]]; 59 left[right[head[x]]]=id; 60 left[id]=head[x]; 61 right[head[x]]=id; 62 } 63 } 64 void remove(int c) 65 { 66 for(int i=down[c];i!=c;i=down[i]) 67 { 68 left[right[i]]=left[i]; 69 right[left[i]]=right[i]; 70 } 71 } 72 void reback(int c) 73 { 74 for(int i=up[c];i!=c;i=up[i]) 75 { 76 left[right[i]]=right[left[i]]=i; 77 } 78 } 79 bool bj[maxn]; 80 int A() 81 { 82 int ans=0; 83 for(int c=right[0];c!=0;c=right[c]) 84 { 85 bj[c]=true; 86 } 87 for(int c=right[0];c!=0;c=right[c]) 88 { 89 if(bj[c]) 90 { 91 ans++; 92 bj[c]=false; 93 for(int i=down[c];i!=c;i=down[i]) 94 { 95 for(int j=right[i];j!=i;j=right[j]) 96 { 97 bj[col[j]]=false; 98 } 99 } 100 } 101 } 102 return ans; 103 } 104 bool danc(int step) 105 { 106 if(A()+step>k)//剪枝 107 { 108 return false; 109 } 110 if(right[0]==0) 111 { 112 return step<=k; 113 } 114 int c=right[0]; 115 for(int i=c;i!=0;i=right[i]) 116 { 117 if(num[i]<num[c]) 118 { 119 c=i; 120 } 121 } 122 for(int i=down[c];i!=c;i=down[i]) 123 { 124 remove(i); 125 for(int j=right[i];j!=i;j=right[j]) 126 { 127 remove(j); 128 } 129 if(danc(step+1)) 130 { 131 return true; 132 } 133 for(int j=left[i];j!=i;j=left[j]) 134 { 135 reback(j); 136 } 137 reback(i); 138 } 139 return false; 140 } 141 }dlx; 142 struct node//小岛信息 143 { 144 ll x,y; 145 }no[65]; 146 ll dis(node a,node b)//计算距离 147 { 148 ll dx=a.x-b.x; 149 if(dx<0) 150 { 151 dx=-dx; 152 } 153 ll dy=a.y-b.y; 154 if(dy<0) 155 { 156 dy=-dy; 157 } 158 return dx+dy; 159 } 160 int main() 161 { 162 int t,ans=0;; 163 scanf("%d",&t); 164 while(t--) 165 { 166 ans++; 167 int n; 168 ll x[65],y[65]; 169 scanf("%d %d",&n,&k); 170 for(int i=1;i<=n;i++) 171 { 172 scanf("%lld %lld",&no[i].x,&no[i].y); 173 } 174 ll le=0,rig=100000000000LL; 175 while(rig-le>0) 176 { 177 dlx.init(n); 178 ll mid=(rig+le)/2; 179 for(int i=1;i<=n;i++) 180 { 181 for(int j=1;j<=n;j++) 182 { 183 if(dis(no[i],no[j])<=mid)//岛之间的距离比航距小时 184 { 185 dlx.link(i,j); 186 } 187 } 188 } 189 if(dlx.danc(0))//如果当前航距需要的最少飞机的数量比k小为true 190 { 191 rig=mid; 192 } 193 else 194 { 195 le=mid+1; 196 } 197 } 198 printf("Case #%d: %lld ",ans,le); 199 } 200 }