zoukankan      html  css  js  c++  java
  • hdu 4435(第37届ACM/ICPC天津赛区现场赛E题)

    题意:给定每个点在平面内的坐标,要求选出一些点,在这些点建立加油站,使得总花费最少(1号点必须建立加油站)。在i点建立加油站需要花费2^i。建立加油站要求能使得汽车从1点开始走遍全图所有的点并回到1点,途中汽车加油次数不限,每个加油站的使用次数不限,但是汽车油箱有上限d(加满油可以跑距离d)。

    分析:突破口在于在i号点建立加油站的费用为2^i,这样特殊的花费会使得我们有一个贪心的规律,就是尽量不在号比较大的点建加油站,如果在n号点建立加油站的费用会大于在除n以外的所有点都建加油站的总费用。所以我们可以先尝试把除n以外的所有点建立加油站,观察是否满足要求。若满足则说明我们必然不会在n点建立加油站,若不满足我们就一定要在n点建加油站。若需要建,我们就建,然后就不用再考虑n点了,在确定了n点之后,我们用同样的方法来观察n-1号点是否需要建立加油站,即将1~n-2号点都建立加油站,观察是否满足要求。以此类推,可以推出所有点的情况。

    接下来我们需要解决对于一种给定的加油站建立情况,我们如何判断它是否满足题中的travel around的要求。分为两部判断,1.判断所有加油站是否可达(从1号点开始广搜,若到当前点距离<=d则入队)。2.判断其余点是否可达(刚才的广搜过程可以顺便标出每个点到最近的加油站的距离,要求能从加油站到该点并返回加油站,所以点到加油站的距离必须小于等于d/2)。若满足这两点必然符合要求,否则不符合要求。

    View Code
    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    
    #define maxn 150
    #define inf 0x3f3f3f3f
    
    struct Point
    {
        int x, y;
    } point[maxn];
    
    int n, d;
    int map[maxn][maxn];
    bool isstation[maxn];
    int q[maxn];
    int dist[maxn];
    bool vis[maxn];
    
    void input()
    {
        for (int i = 0; i < n; i++)
            scanf("%d%d", &point[i].x, &point[i].y);
    }
    
    void make()
    {
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                map[i][j] = ceil(
                        sqrt(
                                (point[i].x - point[j].x)
                                        * (point[i].x - point[j].x)
                                        + (point[i].y - point[j].y)
                                                * (point[i].y - point[j].y)));
    }
    
    bool ok()
    {
        int front, rear;
    
        memset(vis, 0, sizeof(vis));
        for (int i = 0; i < n; i++)
            if (!isstation[i])
                dist[i] = inf;
            else
                dist[i] = 0;
        front = rear = 0;
        q[rear++] = 0;
        vis[0] = true;
        dist[0] = 0;
        while (front != rear)
        {
            int u = q[front++];
            for (int i = 0; i < n; i++)
                if (!vis[i]&& map[u][i] <= d)
                {
                    dist[i] = min(dist[i], dist[u] + map[u][i]);
                    if (isstation[i])
                    {
                        vis[i] = true;
                        q[rear++] = i;
                    }
                }
        }
        for (int i = 0; i < n; i++)
            if (isstation[i] && !vis[i])
                return false;
            else if (!isstation[i] && dist[i] * 2 > d)
                return false;
        return true;
    }
    
    void work()
    {
        for (int i = 0; i < n; i++)
            isstation[i] = true;
        if (!ok())
        {
            printf("-1\n");
            return;
        }
        for (int i = n - 1; i >= 1; i--)
        {
            isstation[i] = false;
            if (ok())
                continue;
            else
                isstation[i] = true;
        }
        int i = n - 1;
        while (!isstation[i])
            i--;
        for (; i >= 0; i--)
            if (isstation[i])
                putchar('1');
            else
                putchar('0');
        putchar('\n');
    }
    
    int main()
    {
        //freopen("t.txt", "r", stdin);
        while (~scanf("%d%d", &n, &d))
        {
            input();
            make();
            work();
        }
        return 0;
    }
  • 相关阅读:
    创建索引资源正忙的解决方案及原理
    MYSQL统计多个count_mysql 不同条件count ,多条件count()
    spark foreachPartition算子
    nginx部署安装
    Sqoop 并行度调整 m 以及 splitby
    sqoop报错
    idea 下1载
    Linux下nginx的安装
    电脑清除C盘文件夹
    深入理解计算机原理(csapp第三版)——datalab
  • 原文地址:https://www.cnblogs.com/rainydays/p/2742037.html
Copyright © 2011-2022 走看看