hdu 4435 2012天津现场赛

题目:有N个城市,1.。。N,现在从1 乘汽车出发,但是汽车最多只能走D距离,然后必须加油,现在要在这N个城市建一些加油站使得最后可以遍历所有的城市,然后回到原来的城市。在编号i的城市建站的费用为 2^(i-1)。要求费用最少。

思路:通过观察可以发现,建站的费用有奇妙之处,因为 2^0+2^1...+2^i-1 < 2^i。那么也就是说如果在前i-1个城市都建站可以满足条件那么费用都要比在第i个城市建站来的少。因此,我们可以利用贪心思路,假设在所有的城市都建站,然后从编号最大的城市开始check,判断在该城市不建站是否可以到达所有城市,如果可以就不建站。否则建站。


#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn=150;
const int inf=1000000000;

struct Point{
	int x,y;
}p[maxn];

int dist[maxn][maxn],station[maxn],d[maxn];//dist记录两个城市距离,station记录是否建站,d记录到最近加油站的距离
int queue[maxn<<2],front,rear;
bool vis[maxn],flag;
int N,D;

int getdist(Point a,Point b){
	int dx=a.x-b.x;
	int dy=a.y-b.y;
	return ceil(sqrt(dx*dx+dy*dy+0.0));
}

bool check(){//dfs
	memset(vis,false,sizeof(vis));
	front=rear=0;
	for(int i=0;i<N;i++){
		if(station[i])d[i]=0;
		else d[i]=inf;
	}
	queue[rear++]=0;
	vis[0]=true;
	while(front<rear){
		int u=queue[front++];
		for(int i=0;i<N;i++){
			if(!vis[i]&&dist[u][i]<=D){
				d[i]=min(d[i],d[u]+dist[u][i]);
				if(station[i])queue[rear++]=i,vis[i]=true;
			}
		}
	}
	for(int i=0;i<N;i++){
		if(station[i]&&!vis[i]||!station[i]&&d[i]*2>D)return false;
	}
	return true;
}

void solve(){
	flag=true;
	for(int i=0;i<N;i++)station[i]=1;
	if(!check()){flag=false;return;}
	for(int i=N-1;i>=0;i--){
		station[i]=0;
		if(!check())station[i]=1;
	}
}

int main(){

	while(scanf("%d%d",&N,&D)==2){

		for(int i=0;i<N;i++)scanf("%d%d",&p[i].x,&p[i].y);
		for(int i=0;i<N;i++)for(int j=0;j<N;j++)dist[i][j]=getdist(p[i],p[j]);
		solve();
		if(flag){
			int i=N-1;
			while(!station[i])i--;
			for(;i>=0;i--)printf("%d",station[i]);
			putchar(10);
		}
		else puts("-1");
	}
}


你可能感兴趣的:(hdu 4435 2012天津现场赛)