您的位置:首页 > 其它

HDU 4435 charge-station

2014-09-12 18:21 302 查看
题意:给出N个点及其坐标,一个人开车从第一个点开始,要遍历完所有城市,同时返回第一个城市。汽车加一次油,有最大的行驶距离D。所以,要在一些城市建加油站才能完成上面的任务。

对于给出的的第i个城市,建加油站的费用为2 ^ (i-1).问,如何建加油站,让花费最小,同时可以完成城市的遍历。

思路:对于花费,我们可以看到一个有趣的性质:在前i-1个城市建加油站的费用比第i个城市建加油站的还要小。

那么,如果在前i个城市建加油站能满足要求,就不需要在第i个城市建加油站。这样,我们就能够从最后一个城市开始,贪心枚举能不建加油站的城市。

这样,这个问题就变成了判定性问题,给定建加油站的方案,判断能否遍历完所有的城市并返回。

我们可以用搜索完成这个判定性问题。

这个图中,一共有两种点,有加油站,没加油站。对于有加油站的点,从某个城市到达,那一定可以回到该城市。

而对于没有加油站的城市,那他的油要保证能够往返。即,该点到最近的加油站的距离小于等于最大行驶距离的二倍。

代码如下:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;

const int MAX = 200;
int N,D;
int d[MAX][MAX];
int dis[MAX];
double x[MAX],y[MAX];
bool vis[MAX];
bool build[MAX];
int que[MAX],front,tail;

bool bfs()
{
memset(vis,0,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
for(int i = 0 ; i < N; ++i)
if(build[i]) dis[i] = 0;
front = tail = 0;
que[tail++] = 0;
vis[0] = true;
while(front < tail){
int u = que[front++];
for(int i = 0; i < N; ++i){
if(!vis[i] && d[u][i] <= D){
dis[i] = min(dis[i],d[u][i]);
if(build[i]){
vis[i] = true;
que[tail++] = i;
}
}
}
}
for(int i = 0; i < N; ++i){
if(build[i] && !vis[i])
return false;
else if(!build[i] && 2 * dis[i] > D)
return false;
}
return true;
}

int main(void)
{
//freopen("input.txt","r",stdin);
while(scanf("%d %d", &N,&D) != EOF){
for(int i = 0; i < N; ++i)
scanf("%lf %lf", &x[i], &y[i]);
for(int i = 0; i < N; ++i){
for(int j =0; j < i; ++j)
d[i][j] = d[j][i]= ceil(sqrt((x[i] - x[j]) * (x[i] - x[j])
+ (y[i] - y[j]) * (y[i] - y[j])));
d[i][i] = 0;
}
fill(build,build + MAX,true);
if(!bfs()){
puts("-1");
continue;
}
else{
for(int i = N - 1; i > 0; --i){
build[i] = false;
if(!bfs()) build[i] = true;
}
int i = N-1;
while(!build[i]) i--;
for(; i >= 0; --i)
printf("%d",build[i]);
puts("");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: