hdu 4435 charge-station

时间:2023-03-08 17:21:38
// 题意 从1出发逛完N个点回到出发点 要在这N个点选择性建设加油站 车每次加满油最多可以行使D米
// 然后最少要花多少钱才能达到上述要求
// 注意到 第i个城市的花费是 2^(i-1) 所以 我就从N枚举到2
// 尽量让 i大的不建加油站 应为前i-1个加油站总费用都没有第i个加油站一个的费用多
// 难点是怎么判断一组方案的可行性
// 注意到 若i 不建加油站 那么必须存在某个加油站和他距离等于小于 (D+1)/2
// 这样对于每组方案进行搜索,看下是否每个点都是可以达到并可以回到起点的
//
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cmath>
using namespace std;
#define INF 100000000
bool mark[];
int dis[][];
int N,D;
double sq(double x1,double y1,double x2,double y2){
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
bool visit[];
int ct;
void dfs(int u){// 判断有无解
visit[u]=true;
ct++;
for(int i=;i<=N;i++)
if(!visit[i]&&dis[u][i]<=D){
dfs(i);
}
}
void OK(int u,int lt){// 判断方案的可行性
if(mark[u]){
lt=D,visit[u]=true;
ct++;
}
else{
if(lt>=(D+)/) visit[u]=true,ct++;
else return;
}
for(int i=;i<=N;i++)
if(u!=i&&!visit[i]&&dis[u][i]<=lt)
OK(i,lt-dis[u][i]);
} int main(){ int rc[][];
int i,j;
while(scanf("%d %d",&N,&D)!=EOF){
for(i=;i<=N;i++) mark[i]=true;
for(i=;i<=N;i++)
scanf("%d %d",&rc[i][],&rc[i][]);
if(N==){printf("0\n");continue;}
for(i=;i<N;i++)
for(j=i+;j<=N;j++){
double t=sq(rc[i][],rc[i][],rc[j][],rc[j][]);
int ti=ceil(sqrt(t));
dis[i][j]=dis[j][i]=ti;
}
memset(visit,,sizeof(visit));
ct=;
dfs();
if(ct<N) {printf("-1\n");continue;}
for(i=N;i>;i--){ // 枚举方案
mark[i]=false;
ct=;
memset(visit,,sizeof(visit));
OK(,);
if(ct<N)
mark[i]=true;
}
for(i=N;i>;i--)if(mark[i]) break;
for(;i>;i--) if(mark[i])printf("");else printf("");
printf("\n");
}
return ;
}