最后输出的答案实际上从右往左第i位就代表第i个城市是否有加油站。
首先要写一个bfs函数判断一个图能否满足题目要求:
dfs时从第一个城市开始,设bfs到当前城市cur,如果cur无加油站则不能判断从它能到达哪个城市,直接continue。对于其他每个城市i,如果i有加油站,那么和cur的距离只要小于D就可以被访问到,如果i没有加油站,那么和cur距离需要小于D/2(因为到i后还需要返回cur)。最后如果没有把所有城市都遍历到就不行。
然后从最后一个城市开始测试能否删除,首先必须要有一个有加油站的城市与它距离小于D/2才可能删。满足这个条件后还要调用bfs确认整个图是否可行。如果都可行就删除。
最后倒序输出就是答案。
代码:
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <cmath>
using namespace std;
#define eps 1e-7
int N,D;
struct node {
int x,y;
}G[130];
bool vis[130];
bool exist[130];
double dist(int a,int b){
double tx=G[a].x-G[b].x;
double ty=G[a].y-G[b].y;
return ceil(sqrt(tx*tx+ty*ty));
}
bool bfs(){
queue <int> Q;
Q.push(1);
memset(vis,0,sizeof(vis));
vis[1]=1;
while(!Q.empty()){
int cur=Q.front();
Q.pop();
if(exist[cur]){
for(int i=1;i<=N;i++){
if(!vis[i]&&exist[i]){
if(dist(i,cur)<D+eps){
vis[i]=1;
Q.push(i);
}
}
else if(!vis[i]&&!exist[i]){
if(dist(i,cur)<D/2+eps){
vis[i]=1;
Q.push(i);
}
}
}
}
}
for(int i=1;i<=N;i++){
if(!vis[i]) return 0;
}
return 1;
}
void solve(){
for(int i=N;i>=1;i--){
for(int j=1;j<=N;j++){
if(exist[j]&&dist(i,j)<D/2+eps){
if(i==j)continue;
exist[i]=0;
if(!bfs()){
exist[i]=1;
}
}
}
}
}
int main(){
while(~scanf("%d%d",&N,&D)){
for(int i=1;i<=N;i++){
exist[i]=1;
scanf("%d%d",&G[i].x,&G[i].y);
}
if(!bfs()){
printf("-1\n");
continue;
}
solve();
bool flag=0;
exist[1]=1;
for(int i=N;i>=1;i--){
if(exist[i]) flag=1;
if(flag){
if(exist[i])printf("1");
else printf("0");
}
}
printf("\n");
}
return 0;
}