[NOI2003]智破连环阵
题目大意:给出地图上N个目标点,M台武器(只能用一次)。每个武器启动后,将距它距离不超过K范围内的符合要求的目标全部摧毁(符合要求:摧毁目标必须按编号顺序,而且同一时刻只有一个武器是启动的),求摧毁全部目标需要动多少武器
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 110
using namespace std;
int n,m,f,point,pos[N][2],wea[N][2],maxn[N][N],map[N][N],res,cov[N],x[N][N],dis[N];
bool bomb[N][N],len[N][N],vis[N];
int dist(int a,int b){return a*a+b*b;}
void init(){
int i,j;
scanf("%d%d%d",&n,&m,&f);
memset(bomb,0,sizeof(bomb));
memset(maxn,0,sizeof(maxn));
memset(map,0,sizeof(map));
memset(len,0,sizeof(len));
for(i=1;i<=n;i++) scanf("%d%d",&pos[i][0],&pos[i][1]);
for(i=1;i<=m;i++) scanf("%d%d",&wea[i][0],&wea[i][1]);
f*=f;
for(i=n;i>0;i--) for(j=m;j>0;j--)
if(dist(pos[i][0]-wea[j][0],pos[i][1]-wea[j][1])<=f) bomb[j][i]=1;
for(i=1;i<=m;i++){
maxn[i][n+1]=n;
for(j=n;j>0;j--)
if(bomb[i][j]){
maxn[i][j]=maxn[i][j+1];
len[j][maxn[i][j]]=1;
}
else maxn[i][j]=j-1;
}
for(i=n;i>0;i--) for(j=i;j<=n;j++) if(len[i][j])
map[i][++map[i][0]]=j;
dis[n+1]=0;
for(i=n;i>0;i--) dis[i]=1+dis[map[i][map[i][0]]+1];
}
void Add(int u,int v){
for(int i=1;i<=m;i++) if(maxn[i][u]==v)
x[point][++x[point][0]]=i;
}
int Hungary(int u){
if(vis[u]) return false;
vis[u]=true;
for(int i=1;i<=x[u][0];i++){
int v=x[u][i];
if(!cov[v] || Hungary(cov[v])){
cov[v]=u;
return v;
}
}
return 0;
}
void dfs(int i){
if(i>n) res=min(res,point);
if(point + dis[i] >= res) return ;
int u,t,tt;
point++;
x[point][0]=0;
for(u=map[i][0];u>0;u--){
t=map[i][u];
Add(i,t);
memset(vis,0,sizeof(vis));
tt=Hungary(point);
if(tt){
dfs(t+1);
cov[tt]=0;
}
}
point--;
}
int main(){
freopen("DFS.in","r",stdin);
freopen("DFS.out","w",stdout);
init();
res=~0U>>1;
point=0;
dfs(1);
printf("%d\n",res);
}