hdu4435-charge-station

http://acm.hdu.edu.cn/showproblem.php?pid=4435

bfs搜索

大致题意是 给出N个点,让你选择性地建立加油站,在第i个点建立加油站的费用为2^i-1,要使自己能从1号点经过所有点回到原点,

点可以重复经过,加油费用不计,每次加油最多能跑的距离为D。输出的答案是2进制,由费用10进制转化过来就是在第i个点建立加

油站,答案从右往左数第i个值就为1。

第一步判断所有点都建立加油站能不能完成题目的要求,不能输出-1。

能完成要求的话,我们注意到建站费用是和点的编号有关的,比如第i个点建站的费用是等于前i-1个点都建站的费用+1,二进制的规律。

然后我们可以从后往前判断当前加油站能不能拆。

dist数组存从当前点到最近的加油站的距离,判断分两个方面:

如果当前点也有加油站,dist[i] <= D就可以;

如果当前点决定不建立加油站,那么dist[i]要小于D/2;

不符合要求就不能拆这个加油站。

#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "algorithm"
#include "iostream"
#include "queue"
#include "string.h"
using namespace std;
#define maxn  1005 
#define INF 1000000000
int sta[ maxn ] ;
double dist[ maxn ] ;
struct node
{
	int x , y ;
}edge[ maxn ] ;
int num[ maxn ][ maxn ] ;
int used[ maxn ] ;
int n , m ; 
double path( int x , int y )
{
	return sqrt( (edge[ x ].x - edge[ y ].x ) * ( edge[ x ].x - edge[ y ].x ) + ( edge[ x ].y - edge[ y ].y )*( edge[ x ].y - edge[ y ].y ) ) ;
}

int bfs()
{
	queue<int> Q ;
	memset( used , 0 ,sizeof( used ) ) ;
	for( int i = 0 ; i < n ; i++ )
	{
		if( !sta[ i ] )
			dist[ i ] = INF ;
		else
			dist[ i ] = 0 ;
	}
	dist[ 0 ] = 0 ;
	used[ 0 ] = 1 ;
	Q.push( 0 ) ;
	while( !Q.empty() )
	{
		int u = Q.front() ;
		Q.pop() ;
		for( int i = 0 ; i < n ; i++ )
		{
			if( !used[ i ] && num[ u ][ i ] <= m )
			{
				dist[ i ] = min( dist[ i ] , dist[ u ] + num[ u ][ i ] ) ;
				if( sta[ i ] ) 
				{
					used[ i ] = 1 ;
					Q.push( i ) ;
				}
			}
		}
	}
	for( int i = 0 ; i < n ; i++ )
	{
		if( sta[ i ] && !used[ i ] ) 
			return 0 ;
		else if( !sta[ i ] && dist[ i ] * 2 > m )
			return 0 ;
	}
	return 1;
}
void solved()
{
	for( int i = 0 ; i < n ; i++ )
		sta[ i ] = 1 ;
	if( !bfs() )
	{
		puts("-1");
		return ;
	}
	for( int i = n - 1 ; i >= 1 ; i-- )
	{
		sta[ i ] = 0 ;
		if( bfs() )
			continue ;
		sta[ i ] = 1; 
	}
	int temp = n - 1 ;
	while( !sta[ temp ] )
		temp-- ;
	for( int i = temp ; i >= 0 ; i-- )
		printf( "%d" , sta[ i ] ) ;
	printf( "\n" ) ;
}
int main()
{
	while( ~scanf( "%d%d" ,&n , &m ) )
	{
		for( int i = 0 ; i < n ; i++ )
		{
			scanf( "%d%d" ,&edge[ i ].x , &edge[ i ].y ) ;
		}
		for( int i = 0 ; i < n ; i++ )
			for( int j = 0 ; j < n ; j++ )
			{
				num[ i ][ j ] = (int)ceil(path( i , j )) ;
			}
			solved();
	}	
	return 0;
}

题解参照 http://www.cnblogs.com/rainydays/archive/2012/10/27/2742037.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值