1.题目描述:点击打开链接
2.解题思路:本题利用二分+DLX(重复覆盖型)解决。首先,看到最大值最小化,肯定是用二分法解决。但是没有想到的是这题是重复覆盖的模板题==(见识短浅了。。一直在想dfs)。在DLX算法中,关键要明确行和列分别如何确定。显然,这里的行是可能当做机场的城市,列是与该城市距离小于给定的M的城市。这样就可以利用DLX算法了,同时,这道题还可以加上一个剪枝,如果发现剩下的未被覆盖的城市需要建机场的数目h与当前的递归层数d之和大于k,那么就可以直接剪枝了。
3.代码:
#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cctype>
#include<complex>
#include<functional>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define me(s) memset(s,0,sizeof(s))
#define rep(i,n) for(int i=0;i<(n);i++)
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair <int, int> P;
const int maxnode=4005;
const int maxm=65;
const int maxn=65;
const int INF=0x3f3f3f3f;
int k;
struct DLX
{
int n,m,size;
int U[maxnode],D[maxnode],R[maxnode],L[maxnode];
int row[maxnode],col[maxnode];
int head[maxn],S[maxnode];
int ansd,ans[maxn];
void init(int n,int m)
{
this->n=n;
this->m=m;
ansd=INF;
for(int i=0;i<=m;i++)
{
S[i]=0;
U[i]=D[i]=i;
L[i]=i-1,R[i]=i+1;
}
R[m]=0,L[0]=m;
size=m;
memset(head,-1,sizeof(int)*(n+1));
}
void addRow(int r,int c)
{
++S[col[++size]=c];
row[size]=r;
D[size]=D[c];
U[D[c]]=size;
U[size]=c;
D[c]=size;
if(head[r]<0)head[r]=L[size]=R[size]=size;
else
{
R[size]=R[head[r]];
L[R[head[r]]]=size;
L[size]=head[r];
R[head[r]]=size;
}
}
#define FOR(i,A,s) for(int i=A[s];i!=s;i=A[i])
void remove(int c)
{
FOR(i,D,c)
L[R[i]]=L[i],R[L[i]]=R[i];
}
void restore(int c)
{
FOR(i,U,c)
L[R[i]]=R[L[i]]=i;
}
int v[maxnode];
int h()
{
int ret=0;
FOR(i,R,0)v[i]=1;
FOR(c,R,0)
if(v[c])
{
ret++;
v[c]=0;
FOR(i,D,c)FOR(j,R,i)v[col[j]]=0;
}
return ret;
}
bool dfs(int d)
{
if(d+h()>k)return false;
if(!R[0]) return d<=k;
int c=R[0];
FOR(i,R,0)if(S[i]<S[c])c=i;
FOR(i,D,c)
{
remove(i);
FOR(j,R,i)remove(j);
ans[d]=row[i];
if(dfs(d+1))return true;
FOR(j,L,i)restore(j);
restore(i);
}
return false;
}
};
DLX solver;
int T,n;
const int N=65;
struct City
{
ll x,y;
void read()
{
scanf("%I64d%I64d",&x,&y);
}
}c[N];
ll dis(City a,City b)
{
return abs(a.x-b.x)+abs(a.y-b.y);
}
int main()
{
int rnd=0;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
c[i].read();
ll L=0,R=10000000000LL;
while(L<R)
{
ll M=(L+R)/2;
solver.init(n,n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(dis(c[i],c[j])<=M)
solver.addRow(i,j);
if(solver.dfs(0))R=M;
else L=M+1;
}
printf("Case #%d: %I64d\n",++rnd,L);
}
}