團體程序設計天梯賽-練習集 L3-005. 垃圾箱分佈 dijkstra 解題報告

L3-005. 垃圾箱分佈

時間限制
200 ms
內存限制
65536 kB
代碼長度限制
8000 B
判題程序
Standard
作者
陳越

大家倒垃圾的時候,都希望垃圾箱距離自己比較近,但是誰都不願意守着垃圾箱住。所以垃圾箱的位置必須選在到所有居民點的最短距離最長的地方,同時還要保證每個居民點都在距離它一個不太遠的範圍內。

現給定一個居民區的地圖,以及若干垃圾箱的候選地點,請你推薦最合適的地點。如果解不唯一,則輸出到所有居民點的平均距離最短的那個解。如果這樣的解還是不唯一,則輸出編號最小的地點。

輸入格式:

輸入第一行給出4個正整數:N(<= 103)是居民點的個數;M(<= 10)是垃圾箱候選地點的個數;K(<= 104)是居民點和垃圾箱候選地點之間的道路的條數;DS是居民點與垃圾箱之間不能超過的最大距離。所有的居民點從1到N編號,所有的垃圾箱候選地點從G1到GM編號。

隨後K行,每行按下列格式描述一條道路:
P1 P2 Dist
其中P1和P2是道路兩端點的編號,端點可以是居民點,也可以是垃圾箱候選點。Dist是道路的長度,是一個正整數。

輸出格式:

首先在第一行輸出最佳候選地點的編號。然後在第二行輸出該地點到所有居民點的最小距離和平均距離。數字間以空格分隔,保留小數點後1位。如果解不存在,則輸出“No Solution”。

輸入樣例1:
4 3 11 5
1 2 2
1 4 2
1 G1 4
1 G2 3
2 3 2
2 G2 1
3 4 2
3 G3 2
4 G1 3
G2 G1 1
G3 G2 2
輸出樣例1:
G1
2.0 3.3
輸入樣例2:
2 1 2 10
1 G1 9
2 G1 20
輸出樣例2:
No Solution
思路:將垃圾桶編號爲1000+i,然後用dijkstra即可

普通的jijkstra:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define INF 0x3f3f3f3f

int mat[1100][1100], dis[1100];
int n, m, k, d, x, y, v;
///令g1-g10  爲 1000 + i

void dijkstra(int s)
{
    int vis[1100] = {0};
    memset(dis, 0x3f, sizeof(dis));
    for(int i = 1; i <= n; i++)
        dis[i] = mat[s][i];
    for(int i = 1001; i <= 1000+m; i++)
        dis[i] = mat[s][i];
    vis[s] = 1;
    dis[s] = 0;
    while(true)
    {
        int k = -1, mixv = INF;
        for(int i = 1; i <= n; i++)
        {
            if(!vis[i] && mixv > dis[i])
            {
                k = i;
                mixv = dis[i];
            }
        }
        for(int i = 1001; i <= 1000 + m; i++)
        {
            if(!vis[i] && mixv > dis[i])
            {
                k = i;
                mixv = dis[i];
            }
        }
        if(k == -1) break;
        vis[k] = 1;
        for(int i = 1; i <= n; i++)
        {
            if(!vis[i] && (dis[i] > dis[k] + mat[k][i]))
            {
                dis[i] = dis[k] + mat[k][i];
            }
        }
        for(int i = 1001; i <= 1000 + m; i++)
        {
            if(!vis[i] && (dis[i] > dis[k] + mat[k][i]))
            {
                dis[i] = dis[k] + mat[k][i];
            }
        }
    }
}


int main()
{
    char sa[10], sb[10];
    memset(mat, 0x3f, sizeof(mat));
    scanf("%d%d%d%d", &n, &m, &k, &d);
    for(int i = 0; i < k; i++)
    {
        x = y = 0;
        scanf("%s %s %d", sa, sb, &v);
        if(sa[0] != 'G')
        {
            for(int j = 0; sa[j]; j++)
                x = x * 10 + sa[j] - '0';
        }
        else
        {
            for(int j = 1; sa[j]; j++)
                x = x * 10 + sa[j] - '0';
            x += 1000;
        }
        if(sb[0] != 'G')
        {
            for(int j = 0; sb[j]; j++)
                y = y * 10 + sb[j] - '0';
        }
        else
        {
            for(int j = 1; sb[j]; j++)
                y = y * 10 + sb[j] - '0';
            y += 1000;
        }
        mat[x][y] = mat[y][x] = v;
    }
    int mini, mind = 0, f, in = -1, sum = INF;
    for(int i = 1; i <= m; i++)
    {
        f = 0;
        dijkstra(1000 + i);
        int tsum = 0, tmd = INF;
        for(int j = 1; j <= n; j++)
        {
            int td = dis[j];
            if(td > d) {f = 1; break;}
            if(tmd > td) tmd = td;
            tsum += td;
        }
        if(!f)
        {
            if(mind < tmd)
            {
                mind = tmd;
                in = i;
                sum = tsum;
            }
            else if(mind == tmd && tsum < sum)
            {
                mind = tmd;
                in = i;
                sum = tsum;
            }
        }

    }
    if(in == -1)
    {
        printf("No Solution\n");
        return 0;
    }
    printf("G%d\n", in);
    printf("%.1lf %.1lf\n", mind * 1.0, sum * 1.0 / n);
    return 0;
}

用優先隊列優化的dijkstra,少了20多ms

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f

int mat[1100][1100], dis[1100];
int n, m, k, d, x, y, v;
///令g1-g10  爲 1000 + i

struct hep
{
    int id, val;
    hep(){}
    hep(int _id, int _val):id(_id), val(_val) {}
    bool operator < (const hep& a) const
    {
        return val > a.val;
    }
}h;

void dijkstra(int s)
{
    priority_queue<hep> Q;
    int vis[1100] = {0};
    memset(dis, 0x3f, sizeof(dis));
    for(int i = 1; i <= n; i++)
    {
        dis[i] = mat[s][i];
        Q.push(hep(i, mat[s][i]));
    }

    for(int i = 1001; i <= 1000+m; i++)
    {
        dis[i] = mat[s][i];
        Q.push(hep(i, mat[s][i]));
    }
    vis[s] = 1;
    Q.push(hep(s, 0));
    while(!Q.empty())
    {
        int k = -1, mixv = INF;
        hep h = Q.top();
        Q.pop();
        k = h.id;
        if(k == -1) break;
        vis[k] = 1;
        for(int i = 1; i <= n; i++)
        {
            if(!vis[i] && (dis[i] > dis[k] + mat[k][i]))
            {
                dis[i] = dis[k] + mat[k][i];
                Q.push(hep(i, dis[i]));
            }
        }
        for(int i = 1001; i <= 1000 + m; i++)
        {
            if(!vis[i] && (dis[i] > dis[k] + mat[k][i]))
            {
                dis[i] = dis[k] + mat[k][i];
                Q.push(hep(i, dis[i]));
            }
        }
    }
}


int main()
{
    char sa[10], sb[10];
    memset(mat, 0x3f, sizeof(mat));
    scanf("%d%d%d%d", &n, &m, &k, &d);
    for(int i = 0; i < k; i++)
    {
        x = y = 0;
        scanf("%s %s %d", sa, sb, &v);
        if(sa[0] != 'G')
        {
            for(int j = 0; sa[j]; j++)
                x = x * 10 + sa[j] - '0';
        }
        else
        {
            for(int j = 1; sa[j]; j++)
                x = x * 10 + sa[j] - '0';
            x += 1000;
        }
        if(sb[0] != 'G')
        {
            for(int j = 0; sb[j]; j++)
                y = y * 10 + sb[j] - '0';
        }
        else
        {
            for(int j = 1; sb[j]; j++)
                y = y * 10 + sb[j] - '0';
            y += 1000;
        }
        mat[x][y] = mat[y][x] = v;
    }
    int mini, mind = 0, f, in = -1, sum = INF;
    for(int i = 1; i <= m; i++)
    {
        f = 0;
        dijkstra(1000 + i);
        int tsum = 0, tmd = INF;
        for(int j = 1; j <= n; j++)
        {
            int td = dis[j];
            if(td > d) {f = 1; break;}
            if(tmd > td) tmd = td;
            tsum += td;
        }
        if(!f)
        {
            if(mind < tmd)
            {
                mind = tmd;
                in = i;
                sum = tsum;
            }
            else if(mind == tmd && tsum < sum)
            {
                mind = tmd;
                in = i;
                sum = tsum;
            }
        }

    }
    if(in == -1)
    {
        printf("No Solution\n");
        return 0;
    }
    printf("G%d\n", in);
    printf("%.1lf %.1lf\n", mind * 1.0, sum * 1.0 / n);
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章