PAT 1028Gas Station (30)

来源:互联网 发布:gsk数控机床仿真软件 编辑:程序博客网 时间:2024/06/08 07:43

题目

题目描述A gas station has to be built at such a location that the minimum distance between the station and any of the residential housing is as far away as possible.  However it must guarantee that all the houses are in its service range.Now given the map of the city and several candidate locations for the gas station, you are supposed to give the best recommendation.  If there are more than one solution, output the one with the smallest average distance to all the houses.  If such a solution is still not unique, output the one with the smallest index number.输入描述:Each input file contains one test case.  For each case, the first line contains 4 positive integers: N (<= 103), the total number of houses; M (<= 10), the total number of the candidate locations for the gas stations; K (<= 104), the number of roads connecting the houses and the gas stations; and DS, the maximum service range of the gas station.  It is hence assumed that all the houses are numbered from 1 to N, and all the candidate locations are numbered from G1 to GM.Then K lines follow, each describes a road in the formatP1 P2 Distwhere P1 and P2 are the two ends of a road which can be either house numbers or gas station numbers, and Dist is the integer length of the road.输出描述:For each test case, print in the first line the index number of the best location.  In the next line, print the minimum and the average distances between the solution and all the houses.  The numbers in a line must be separated by a space and be accurate up to 1 decimal place.  If the solution does not exist, simply output “No Solution”.输入例子:4 3 11 51 2 21 4 21 G1 41 G2 32 3 22 G2 13 4 23 G3 24 G1 3G2 G1 1G3 G2 2输出例子:G12.0 3.3

解题思路

  • 1.题目的意思是要满足到住宅区的最小的距离最大,如果存在多个最小的值,则取平均值最大的,如果还是相等,则取序号较小的Gas Station。
  • 2.算出每个加油站到所有的住宅区的最短路径就可以了(我这里用Dijkstra算法求最短路径),然后再比较就可以了。
  • 3.sstream中的stringstream可以将string类型的变量转化为其他类型的,这里利用比较方便。
  • 4.对于判断输出,即可利用满足tem_min>index_min或者满足tem_min==index_min&&tem_sum<index_sum就更新index,index_min,index_sum,并且这里从前往后判断,所以能保证前俩项都相同的情况下,取到的是序号较小的。这里我们可以想到设置初始值index=-1,index_min=0,index_sum=INT_MAX

我出错的一些点

  • 1.Dijkstra算法中dist[k]+a[k][i]<dist[i],其中将disk[k]a[k][i]中最大值设为INT_MAX,最后溢出了,害死我了。
  • 2.**对Dijkstra算法不熟悉,此算法的总体思路就是,访问改点并将改点标记为访问,遍历改点领域,借助该点更新Dist[i],并在领域中找到值最小且没有被访问过的点递归访问改点,直到所有点都访问完了就return。**ps,非递归的思路可以看这个非递归Dijkstra算法
  • 3.//要加double,setprecision才会起效果!
    cout << fixed << setprecision(1) << (double)index_min << " " << index_sum / (double)n << endl;

代码

#include <iostream>#include<string>#include<sstream>#include<vector>#include<iomanip>#define MAX 10000using namespace std;int n, m, k, ds;int a[1000 + 10 + 5][1000 + 10 + 5];int dist[1000 + 10 + 5]; int pre[1000 + 10 + 5]; bool visited[1000 + 10 + 5];int str2int(string a){    int b;    if (a[0] == 'G')    {        string tem_a = a.substr(1);        stringstream ss;        ss << tem_a;        ss >> b;        b += n;        return b;    }    else    {        stringstream ss;        ss << a;        ss >> b;        return b;    }}void init(int k){    for (int i = 1; i <= n + m; i++)    {        dist[i] = 100;        visited[i] = false;        pre[i] = -1;    }    dist[k] = 0;    //cout << dist[k] << endl;}void Dijkstra(int k){    if (k == 0)return;    visited[k] = true;    int min = MAX,k1=0;    for (int i = 1; i <= n+m; i++)    {        if (dist[k]+a[k][i]<dist[i])        {            dist[i] = dist[k] + a[k][i];            pre[i] = k;        }        if (dist[i]<min&&!visited[i])        {            k1 = i;            min = dist[i];        }    }    Dijkstra(k1);}int main(){    cin >> n >> m >> k >> ds;    for (int i = 1; i <= n + m; i++)    {        for (int j = 1; j <= n + m; j++)        {            if (i == j)            {                a[i][j] = 0;            }            else            {                a[i][j] = MAX;            }        }    }    string tem_a, tem_b; int tem_c;    int d1, d2;    for (int i = 0; i < k; i++)    {        cin >> tem_a >> tem_b >> tem_c;        d1 = str2int(tem_a);        d2 = str2int(tem_b);        /*cout << tem_a << " " << d1 << endl;        cout << tem_b << " " << d2 << endl;*/        a[d1][d2] = tem_c;        a[d2][d1] = tem_c;    }    int index=-1, index_min=0, index_sum=MAX;    //int i = n + 1;    for (int i=n+1; i <= n+m; i++)    {        //cout << "i:" << i << endl;        init(i);        Dijkstra(i);        int tem_sum = 0, tem_submin = MAX;        bool flag = false;        for (int j = 1; j <= n; j++)        {            if (dist[j]>ds)            {                flag = true;                break;            }            if (dist[j]<tem_submin)            {                tem_submin = dist[j];            }            tem_sum += dist[j];        }        if (flag)            continue;        /*对于判断输出,即可利用满足`tem_min>index_min`或者满足`tem_min==index_min&&tem_sum<index_sum`        就更新`index,index_min,index_sum`,并且这里从前往后判断,所以能保证前俩项都相同的情况下,取到的        是序号较小的。这里我们可以想到设置初始值`index=-1,index_min=0,index_sum=INT_MAX`。*/        if (tem_submin>index_min||(tem_submin==index_min&&index_sum>tem_sum))        {            index = i;            index_min = tem_submin;            index_sum = tem_sum;        }    }    if (index==-1)    {        cout << "No Solution" << endl;    }    else    {        cout << "G" << index - n << endl;        //要加double,setprecision才会起效果!        cout << fixed << setprecision(1) << (double)index_min << " " << index_sum / (double)n << endl;    }    return 0;}
0 0
原创粉丝点击