HDU 4435 charge-station

2012天津赛区现场赛的E题,刚才做模拟比赛的时候和安神讨论了很久,思路没理清。

大致题意是 给出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 <queue>

#include <algorithm>

using std::queue;

using std::min;

const int MAXN = 130;

const int INF = 0x3f3f3f3f;



struct point

{

    int x, y;

}p[MAXN];



int n, d;

int g[MAXN][MAXN], dist[MAXN], sta[MAXN];

bool vis[MAXN];



int pf(int i)

{

    return i * i;

}



double distance(int i, int j)

{

    return sqrt((double)(pf(p[i].x - p[j].x) + pf(p[i].y - p[j].y)));

}



void ReadGraph()

{

    //让点号从0开始则每个点建立加油站的费用2^i

    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 ++)

        {

            g[i][j] = (int)ceil(distance(i, j));

        }

}



bool judge()

{

    queue<int> q;

    memset(vis, false, sizeof vis);

    for(int i = 0; i < n; i ++)

    {

        if(!sta[i]) dist[i] = INF;

        else dist[i] = 0;

    }

    vis[0] = true;

    dist[0] = 0;

    q.push(0);

    while(!q.empty())

    {

        int u = q.front();

        q.pop();

        for(int i = 0; i < n; i ++)

        {

            if(!vis[i] && g[u][i] <= d)

            {

                dist[i] = min(dist[i], dist[u] + g[u][i]);

                if(sta[i])

                {

                    vis[i] = true;

                    q.push(i);

                }

            }



        }

    }

    for(int i = 0; i < n; i ++)

    {

        if(sta[i] && !vis[i])

            return false;

        else if(!sta[i] && dist[i] * 2 > d)

            return false;

    }

    return true;

}



void solve()

{

    for(int i = 0; i < n; i ++)

    {

        sta[i] = 1;

    }

    if(!judge())

    {

        puts("-1");

        return;

    }

    for(int i = n - 1; i >= 1; i --)

    {

        sta[i] = 0;

        if(judge()) continue;

        sta[i] = 1;

    }

    int cur = n - 1;

    while(!sta[cur])

        cur --;

    for( ; cur >= 0; cur --)

    {

        printf("%d", sta[cur]);

    }

    printf("\n");

}



int main()

{

    //freopen("test.in", "r", stdin);

    while(scanf("%d%d", &n, &d) != EOF)

    {

        ReadGraph();

        solve();

    }

    return 0;

}

 

 

 

你可能感兴趣的:(char)