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; }