PAT甲级-1072 Gas Station (30分)(迪杰斯特拉算法即可,DFS会超时)

题目:1072 Gas Station (30分)
分析:路径问题,用DFS会超时,使用迪杰斯特拉得出dis数组即可。注意!!!有个小坑:station不只是1-9,有可能是两位数以上,10,11,等等,因此在输入的时候字符串的处理要注意,不然最后一个测试点会报错。

AC代码(dj):

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <set>
#include <map>
#include <math.h>
#include <queue>
#include <algorithm>
#include <string.h>
#define MAX 999999999
typedef long long ll;
using namespace std;
int n,m,k,ds;
double road[10020][10020];
int visi[10020];
double dis[10020];
//1-1000 1001-1010
//每个候选加油站的距离住宅的所有最小中选一个最大的
//必须保证所有住宅在加油站的服务范围
//有多个选择的话,选平均距离到住宅最小的,还有多个选序号最小的
void dj(int root)
{
    fill(dis,dis+10020,MAX);
    dis[root] = 0;
    for(int i = 1; i <= n+m ;i++)
    {
        int u = -1;
        int mm = MAX;
        for(int j = 1;j<=n+m;j++)
        {
            if(dis[j] < mm && !visi[j])
            {
                u = j;
                mm = dis[j];
            }
        }
        visi[u] = 1;
        for(int j = 1;j <= n+m;j++)
        {
            if(!visi[j] && road[u][j] != 0 && dis[u] + road[u][j] < dis[j])
                dis[j] = dis[u] +road[u][j];
        }
    }
}
int main()
{
    cin>>n>>m>>k>>ds;
    for(int i = 1;i<=k;i++)
    {
        string a,b;
        int x,y;
        double c;
        cin>>a>>b>>c;
        if(a[0] == 'G')
            x = n + stoi(a.substr(1,a.size()-1));
        else
            x = stoi(a);
        if(b[0] == 'G')
            y = n + stoi(b.substr(1,b.size()-1));
        else
            y = stoi(b);
        road[x][y] = road[y][x] = c;
    }
    int idx = -1;
    double max_dis = -1;
    double avg_dis ;
    for(int i = n + 1;i <= n + m;i++)
    {
        int flag = 0;
        fill(visi,visi+10020,0);
        double c_avg_dis = 0;
        double min_dis = MAX;
        dj(i);
        for(int j = 1;j<=n;j++){
            c_avg_dis += dis[j];
            if(dis[j] < min_dis)
                min_dis = dis[j];
            if(dis[j] > ds)
                flag = 1;
        }
        if(flag)
            continue;//超出服务范围

        if(min_dis > max_dis) {
            max_dis = min_dis;
            avg_dis = c_avg_dis;
            idx = i;
        }
        else if(min_dis == max_dis && c_avg_dis < avg_dis)
        {
            avg_dis = c_avg_dis;
            idx = i;
        }
    }
    if(idx == -1) {
        cout<<"No Solution";
        return 0;
    }
    cout<<"G"<<idx-n<<endl;
    printf("%.1f %.1f",max_dis*1.0, avg_dis/n);
    return 0;
}

超时代码(DFS):

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <set>
#include <map>
#include <math.h>
#include <queue>
#include <algorithm>
#define MAX 999999999
typedef long long ll;
using namespace std;
int n,m,k,ds;
double road[10020][10020];
int visi[10020];
double dis[10020];
//1-1000 1001-1010
//每个候选加油站的距离住宅的所有最小中选一个最大的
//必须保证所有住宅在加油站的服务范围
//有多个选择的话,选平均距离到住宅最小的,还有多个选序号最小的
double max_dis = -1;
double avg_dis;

double min_dis = MAX;
double c_dis;
void dfs(int root)
{
    visi[root] = 1;
    if(c_dis < min_dis && c_dis != 0 && root >=1 && root <= n)//找出当前加油站距离最近的一个住宅的距离
        min_dis = c_dis;
    if(c_dis < dis[root] && c_dis != 0 && root >=1 && root <= n)//得出dis数组的值,为距离每个住宅的最近距离
        dis[root] = c_dis;
    for(int i = 1;i <= n + m;i++)
    {
        if(!visi[i] && road[root][i] != 0)
        {
            c_dis += road[root][i];
            dfs(i);
            c_dis -= road[root][i];
        }
    }
    visi[root] = 0;
}
int main()
{
    cin>>n>>m>>k>>ds;
    for(int i = 1;i<=n;i++)
        dis[i] = MAX;
    for(int i = 1;i<=k;i++)
    {
        string a,b;
        int x,y;
        double c;
        cin>>a>>b>>c;
       	if(a[0] == 'G')
            x = n + stoi(a.substr(1,a.size()-1));
        else
            x = stoi(a);
        if(b[0] == 'G')
            y = n + stoi(b.substr(1,b.size()-1));
        else
            y = stoi(b);
        road[x][y] = road[y][x] = c;
    }
    int idx =-1;
    for(int i = n + 1;i <= n + m;i++)
    {
        fill(dis+1,dis+1+n,MAX);
        int flag = 0;
        double c_avg_dis = 0;
        min_dis = MAX;
        dfs(i);
        for(int j = 1;j<=n;j++){
            c_avg_dis += dis[j];
            if(dis[j] > ds)
                flag = 1;
        }
        if(flag)
            continue;//超出服务范围
        if(min_dis > max_dis) {
            max_dis = min_dis;
            avg_dis = c_avg_dis;
            idx = i;
        }
        else if(min_dis == max_dis && c_avg_dis < avg_dis)
        {
            avg_dis = c_avg_dis;
            idx = i;
        }
    }
    if(idx == -1) {
        cout<<"No Solution";
        return 0;
    }
    cout<<"G"<<idx-n<<endl;
    printf("%.1f %.1f",max_dis*1.0, avg_dis/n);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值