1018. Public Bike Management (30)

本文介绍了一种结合Dijkstra算法与深度优先搜索(DFS)的方法,用于解决城市自行车调配问题。通过Dijkstra算法寻找从调度中心到各站点的最短路径,并记录路径上的关键节点。随后使用DFS遍历所有可能的最短路径组合,以确定从中心到问题站点的最佳路径,同时统计所需的自行车数量及剩余自行车。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提交情况:
这里写图片描述

代码:

#include <iostream>
#include <string.h>
#include <vector>
#include <math.h>
using namespace std;
#define Max 501
#define INF 0x3f3f3f3f
int Cmax,n,sp,m;
int visit[Max],dist[Max],weight[Max],w[Max];
int Graph[Max][Max];
vector<int> pre[Max],temp,path;
int minNeed = INF,minRemain = INF;
void Dijkstra ( int start )    //找到最短路径并存储最短路径 
{
    visit[start] = 1;
    for( int i=0; i<=n; ++i)
    {
        int vertex = -1,min = INF;
        for( int j=0;j<=n;++j)   //找到边权最小 
        {
            if( visit[j] == 0 && dist[j] < min )
            {
                vertex = j;
                min = dist[j];
            }
        }   
        visit[vertex] = 1;

        for( int j=0;j<=n;++j)
        {
            if( visit[j] == 0  )
            {
                if( dist[vertex] + Graph[vertex][j] < dist[j] )  //找到了更短的路径 
                {
                    dist[j] = dist[vertex] + Graph[vertex][j]; //记录最短路径长度 
                    pre[j].clear();
                    pre[j].push_back(vertex);   //把最短路径上该节点的前驱节点记录下来 
                }
                else if( dist[vertex] + Graph[vertex][j] == dist[j] ) //最短路径相同 
                {
                    pre[j].push_back(vertex);   //如果有相同的最短路径,则把该前驱节点也记录下来 
                }
            }   
        } 
    }
}
void DFS( int start )
{
    if( start == 0)
    {
        temp.push_back(start);
        int need = 0,remain = 0;   //need为当前车站需要补充的,remain为当前车站后剩余的 
//      cout<<"temp length:"<<temp.size()<<endl;
        for( int i = temp.size()-1;i>=0;--i)
        {
//          cout<<"节点为:"<<temp[i]<<endl;
            if( weight[temp[i]] > 0 )  //如果该车站有盈余,则将剩余的自行车数量加上该盈余 
            {
                remain = remain + weight[temp[i]];
            }
            else //如果当前车站不足(weight[i]<=0) 
            {
                if( remain > abs(weight[temp[i]]) ) //如果剩余的自行车数量大于所缺少的 
                {
                    remain = remain - abs(weight[temp[i]]);
                }
                else  //remain <= abs(weight[i])
                {
                    need += abs(weight[temp[i]]) - remain;
                    remain = 0;
                }
            }
        }
//      cout<<need<<"***"<<remain<<endl;
        if( need < minNeed )  //需要从PBMC带的自行车数量更少 
        {
            minNeed = need;
            minRemain = remain;
            path = temp;
        }
        else if( need == minNeed && remain < minRemain ) //如果从PBMC带的自行车相同,
        {                                                // 那么选择从问题车站带回最少的 
            minRemain = remain;
            path = temp;
        }
        temp.pop_back();
        return ;
    }
    temp.push_back(start);
    for( int i=0;i<pre[start].size();++i )
    {
        DFS(pre[start][i]);
    }
    temp.pop_back();
}
int main ()
{
    cin>>Cmax>>n>>sp>>m;
    int pbmc = 0;
    for( int i=1;i<=n;++i )
    {
        cin>>weight[i];
        weight[i] = weight[i] - Cmax/2;
        memset(Graph[i],INF,sizeof(Graph[i]));
    }
    memset(Graph[0],INF,sizeof(Graph[0]));  
    for( int i=1;i<=m;++i )
    {
        int a,b;
        cin>>a>>b;
        cin>>Graph[a][b];
        Graph[b][a] = Graph[a][b];
    }
    //初始化
    for( int i=0; i<=n; ++i)
    {
        if( Graph[pbmc][i] != INF )
        {
            dist[i] = Graph[pbmc][i];
            w[i] = weight[i];
            pre[i].push_back(pbmc);
        }
        else
            dist[i] = INF;      
    }
    Dijkstra(pbmc);
//  for( int i=0;i<=n;++i )  //查看最短路径上的前驱 
//  {
//      cout<<"第"<<i<<"节点的前驱:"; 
//      for( int j=0;j<pre[i].size();++j )
//      {
//          if( j == pre[i].size()-1 )
//              cout<<pre[i][j]<<endl;
//          else
//              cout<<pre[i][j]<<" ";
//      }
//  }
//  for( int i=0;i<=n;++i )  //查看weight数组 
//  {
//      if( i == n)
//          cout<<weight[i]<<endl;
//      else
//          cout<<weight[i]<<" ";
//  }
//  for( int i=0;i<=n;++i )  //查看dist数组 
//  {
//      if( i == n)
//          cout<<dist[i]<<endl;
//      else
//          cout<<dist[i]<<" ";
//  }
    DFS(sp);  //从问题车站开始。该DFS算法并不是纯粹的深度优先算法。利用DFS遍历到达sp的最短路径 
    cout<<minNeed<<" ";
    for( int i = path.size()-1;i>=0;--i )
    {
        if( i == 0 )
            cout<<path[i]<<" ";
        else
            cout<<path[i]<<"->";
    }
    cout<<minRemain<<endl;
    return 0;
}

这道题还是挺不错的,我不会做,看了算法笔记之后才明白的。
算法思想:利用Dijkstar求出最短路径,但是并不是只求最短的长度,还记录下最短路径上某一个节点的前驱节点,如果有相同的最短路径,那么同时也记录下来,放在某一个数组中。而后利用DFS算法,从问题车站开始,依次遍历到达问题车站的最短路径,在遍历过程统计需要的自行车和剩余的自行车。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值