题意:一辆汽车从起点开始经过所有的城市再回到起点,汽车加满油最多能行驶D米,问应该在哪个城市建立加油站使得汽车能满足上面的要求,在i城市建立一个加油站花费2^i-1 问怎么样建使得花费最小
思路:由于2^0+2^1+2^2+...+2^i-1<2^i,所以尽量不建在i大的点就尽量不建,所以采用贪心法,先假设所有点都建,然后从大到小枚举,若满足i点不用建的话就不用建,去掉,然后重复以上步骤
注意:题目要求输出费用的二进制,其实就是把建加油站的位置倒过来输出就行
代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
using namespace std;
int n;
double D;
struct node
{
double x,y;
} a[150];
int state[150];
int dd[150][150];
int vis[150];
int dis(double x1,double y1,double x2,double y2)
{
return ceil(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
}
bool check()
{
memset(vis,0,sizeof(vis));
int num=1;
queue<int>q;
vis[0]=1;
q.push(0);//把建加油站放进去
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0; i<n; i++)
{
if(!vis[i])
{
if(state[i]==1)
{
if(dd[u][i]<=D)
{
vis[i]=1;
q.push(i);
num++;
}
}
else if( dd[u][i]*2 <=D)
{
vis[i]=1;
num++;
}
}
}
}
if(num==n)return true;
else
return false;
}
int main()
{
while(scanf("%d%lf",&n,&D)!=EOF)
{
for(int i=0; i<n; i++)
scanf("%lf%lf",&a[i].x,&a[i].y);
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
dd[i][j]=dis(a[i].x,a[i].y,a[j].x,a[j].y);
}
}
for(int i=0; i<n; i++)
state[i]=1;
int ff=0;
for(int i=n; i>=1; i--)
{
state[i]=0;
if(!check())
{
state[i]=1;
if(i==n)
{
ff=1;
break;
}
}
}
if(ff)
{
printf("-1\n");
continue;
}
int f=0;
for(int i=n-1; i>=0; i--)
{
if( f || state[i]==1)//去掉前导0
{
printf("%d",state[i]);
f=1;
}
}
printf("\n");
}
return 0;
}