HDU 4435 charge-station - from lanshui_Yang

         题目大意:这里有n个城市, 编号为1 ~ n , 你是一个旅行家,要从城市1 出发,经过所有城市,然后回到城市1 ,(注意:每个城市可以访问多次) , 你的交通工具是一辆摩托车, 油箱的容量为 d 升,并且每升油可以使摩托车行驶 1 公里,为了使到所有城市旅游成为可能, 要在一些城市建造加油站,并且在城市 i 建造加油站的费用为2 ^ (i - 1) , 请设计一个方案决定在哪些城市建加油站可以使任务完成并且建造费用最低,如果没有办法完成任务,就输出-1 。 

        解题思路:首先,可以发现的是,在每个城市建造加油站的费用有如下特点,即:在城市 i 建造加油站的费用 比 在所有(编号为 1 ~ i - 1)城市建造加油站的总费用 高 , 因此,就可以从 第 i 个城市往前枚举,假设城市 i 没有加油站,而所有(编号为1 ~ i - 1)的城市都有加油站,如果,此时能完成任务,那么说明不用在城市 i 建立加油站,否则,必须在城市 i 建立加油站。

        请看代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<cctype>
#include<algorithm>
#include<string>
#define PI acos(-1.0)
#define maxn 1000
#define INF 1<<25
typedef long long ll;
using namespace std ;
const int MAXN = 201 ;
struct Node
{
    int x ;
    int y ;
} s[MAXN] ;
int p[MAXN] ;  // 记录每个城市是否有加油站,有的话为 1 ,否则,为 0
int n , d ;
double td ;
int dis[MAXN][MAXN] ; // 记录城市之间的距离
int cnt ;
bool vin[MAXN] ; // 标记数组
int dist(Node a , Node b)
{
    return ceil(sqrt((a.x - b.x) * (a.x - b.x)+ (a.y - b.y) * (a.y - b.y))) ;
}
void init()
{
    int i , j ;
    for(i = 1 ; i <= n ; i ++)
    {
        scanf("%d%d" , &s[i].x , &s[i].y) ;
    }
    for(i = 1 ; i <= n ; i ++)
    {
        for(j = 1 ; j <= n ; j ++)
        {
            dis[i][j] = dist(s[i] , s[j]) ;
        }
        dis[i][j] = 0 ;
    }
}
queue <int> q ;
int bfs(int u)
{
    memset(vin , 0 , sizeof(vin)) ;
    while (!q.empty()) q.pop() ;
    cnt = 1 ;
    vin[u] = 1 ;
    q.push(u) ;
    int tmp ;
    while (!q.empty())
    {
        tmp = q.front() ;
        q.pop() ;
        int v ;
        for(v = 1 ; v <= n ; v ++)
        {
            if(!vin[v])
            {
                if(p[tmp])
                {
                    if(p[v])  // 如果当前城市有加油站
                    {
                        if(dis[tmp][v] <= d)
                        {
                            vin[v] = 1 ;
                            cnt ++ ;
                            q.push(v) ;
                        }
                    }
                    else
                    {
                        if(dis[tmp][v] <= td)
                        {
                            vin[v] = 1 ;
                            cnt ++ ;
                            q.push(v) ;
                        }
                    }
                }
            }
        }
    }
    if(cnt == n)
        return 1 ;
    else
        return 0 ;
}
void solve()
{
    td = d / 2.0 ;  // td 为油箱容量的一半
    int i ;
    for(i = 1 ; i <= n ; i ++)  // 初始化,认为每个城市都有加油站
    {
        p[i] = 1 ;
    }
    int flag ;
    flag = bfs(1) ;
    if(flag == 0)
    {
        printf("-1\n") ;
        return ;
    }
    for(i = n ; i >= 2 ; i --) // 城市 1 肯定必须有加油站,所有从n —> 2 枚举
    {
        p[i] = 0 ;
        flag = bfs(1) ;
        if(flag == 0)
        {
            p[i] = 1 ;
        }
    }
    int first = 0 ;
    for(i = n ; i >= 1 ; i --)
    {
        if(p[i] == 1)
        {
            first = 1 ;
        }
        if(first)
            printf("%d" , p[i]) ;
    }
    puts("") ;
}
int main()
{
    while (scanf("%d%d" , &n , &d) != EOF)
    {
        init() ;
        solve() ;
    }
    return 0 ;
}


你可能感兴趣的:(搜索,想法)