题意:给出N个城市,从1开始需要遍历所有点,选择一些点建立加油站,使得花费最少 第i个城市要花费 2^(i-1)
思路: 因为建造最后一个加油站的花费是前面全部建造加油站的总和 所以从n开始遍历 看哪个可以不建造加油站(代码中的check) 用bfs检查 从加油站出发遍历到各个可以到达的点 并遍历出距离每个点的最近的加油站的距离dist[i]是多少 最后检查是否都能走到 可以返回true 不然返回false
代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
const int INF = 10000000000;
int n, d, g[105][105], dist[105], res[105];
bool check()
{
bool vis[105];
memset(vis, false, sizeof(vis));
queue<int >Q;
for(int i=0;i<n;i++)
{
if(res[i]) dist[i]=0;
else dist[i]=INF;
}
Q.push(0);
vis[0]=true;
while(!Q.empty())
{
int u=Q.front();
Q.pop();
for(int i=0;i<n;i++)
{
if(vis[i]==false&&g[u][i]<=d)
{
dist[i]=min(dist[i], dist[u]+g[u][i]);
if(res[i])
{
Q.push(i);
vis[i]=true;
}
}
}
}
for(int i=0;i<n;i++)
{
if(res[i]==1&&!vis[i])
return false;
else if(res[i]==0&&dist[i]*2>d)
return false;
}
return true;
}
int main()
{
while(~scanf("%d%d", &n, &d))
{
double a[105], b[105];
for(int i=0;i<n;i++)
{
scanf("%lf%lf", &a[i], &b[i]);
}
memset(g, 0, sizeof(g));
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i==j)
continue;
g[i][j]=g[j][i]=ceil(sqrt((a[i]-a[j])*(a[i]-a[j])+(b[i]-b[j])*(b[i]-b[j])));
}
}
for(int i=0;i<=n;i++)
res[i]=1;
if(!check())
{
printf("-1\n");
continue;
}
for(int i=n-1;i>0;i--)
{
res[i]=0;
if(!check())
res[i]=1;
}
int flag=0;
for(int i=n-1;i>=0;i--)
{
if(res[i]==1)
flag=1;
if(flag==1)
printf("%d", res[i]);
}
printf("\n");
}
}