数据结构之Public Bike Management问题

本文介绍了一个基于Dijkstra算法的C++程序,用于解决杭州公共自行车服务中调整车站自行车数量的最短路径问题。程序通过监测各站的自行车数量,寻找从公共自行车管理中心到问题站点的最短路径,并计算最少需要搬运的自行车数量。程序首先读取数据,然后利用Dijkstra算法找到最小距离路径,并回溯找出最优搬运路径。最后,程序找出搬运自行车最少的路径并输出。
摘要由CSDN通过智能技术生成

前言

在最近整理大学前两年学的内容时,突然发现了这个初级数据结构程序,主要是根据边的权重来给出最优解。现发布在这里,希望可以给学习的同袍们一点帮助。

题目要求

8-1 Public Bike Management

There is a public bike service in Hangzhou City which provides great convenience to the tourists from all over the world. One may rent a bike at any station and return it to any other stations in the city.

The Public Bike Management Center (PBMC) keeps monitoring the real-time capacity of all the stations. A station is said to be in perfect condition if it is exactly half-full. If a station is full or empty, PBMC will collect or send bikes to adjust the condition of that station to perfect. And more, all the stations on the way will be adjusted as well.

When a problem station is reported, PBMC will always choose the shortest path to reach that station. If there are more than one shortest path, the one that requires the least number of bikes sent from PBMC will be chosen.

在这里插入图片描述
在这里插入图片描述
Sample Input:

10 3 3 5
6 7 0
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1

Sample Output:

3 0->2->3 0

具体代码

#include <iostream>
#include <vector>
#include <iterator>
#include <set>
#include <algorithm>
#include <stdio.h>
#include <map>

using namespace std;

#define INT_MAX 1000000


typedef struct infomation
{
    int bike = 0;   //bikes stores how many bikes is in the station
    int path = 0;   // path stores the minimal distance fron PBMC
    int carrybike;  // how many bikes we must carry
    int surplus = 0;// how many bikes will be brought back
    vector<int> pre ;   //vector pre stores the nodes precedes the node
    vector<int> Next;   //vector Next stores the successor nodes
    int cnt = 0;    // cnt refers to the current reference of the procedure
}Node;

vector<Node> chain; //store the path of nodes
int maxbike,totaln,target,roadnum;  //maxbike : the capacity of each station
//totaln:the number of stations
//roadnum:the number of roads
set<int> vis;   //store the visited nodes
vector<vector<int> > connect;   //the matrix in which connect[i][j] stands for the distance between i and j otherwise 0

int q;  //a temp variable to accomplish function comp
bool comp(const int& a,const int& b)    //comp is the rule of sorting
{
    return connect[q][a] < connect[q][b];
}

void Read_Data()
{
    cin >> maxbike >> totaln >> target >> roadnum;      //maxbike : the capacity of each station
    //totaln:the number of stations    roadnum:the number of roads
    
    //initialize the matrix storing distances
    vector<int> yy(totaln+1,0);
    for(int i=0;i<=totaln;i++)
    {
        connect.push_back(yy);
    }
    
    Node cur;
    chain.push_back(cur);
    for(int i=1;i<=totaln;i++)
    {
        cin >> cur.bike;
        chain.push_back(cur);
    }
    
    //record the distance in the connect matrix
    //also record the successor and precedence of each node
    int st,en,Val;
    for(int i=0;i<roadnum;i++)
    {
        cin >> st >> en >> Val;
        connect[st][en]=connect[en][st]=Val;
        chain[st].Next.push_back(en);
        chain[en].Next.push_back(st);
    }
    
    //sort the vector next by the comparing function comp
    for(int i=0;i<=totaln;i++)
    {
        q = i;
        sort(chain[i].Next.begin(),chain[i].Next.end(),comp);
    }
    
    vis.insert(0);
}

// this module is to find the minimal path
// the function mainly use dijkstra algorithm but the details may be different
void minpath()
{
    map<int,int> m; // record the possible minimal pairs of nodes
    
    set<int> :: iterator itset = vis.begin();
    
    //record the minimal distance to the nodes which is not in the visited set and record some information(dijkstra algorithm)
    int minnext,minpre,min=INT_MAX,minbike=-1000000;
    
    while(itset != vis.end())
    {
        
        // if the node has already been visited ,then skip it.
        while(chain[*itset].cnt < chain[*itset].Next.size() && vis.find((chain[*itset].Next)[chain[*itset].cnt]) != vis.end())
        {
            (chain[*itset].cnt)++;
        }
        
        // if this node has no proper next node to consider,then consider the next node by increasing iterator itset
        if(chain[*itset].cnt == chain[*itset].Next.size())
        {
            itset++;
            continue;
        }
        
        //if the path to current node equals min, then refresh the information.
        if(chain[*itset].path + connect[*itset][(chain[*itset].Next)[chain[*itset].cnt]] == min)
        {
            minnext = (chain[*itset].Next)[chain[*itset].cnt];
            minpre = *itset;
            m[minpre] = minnext;
            min =  chain[*itset].path + connect[*itset][(chain[*itset].Next)[chain[*itset].cnt]] ;
        }
        
        //if the path to current node is less than min, then refresh the information.
        if(chain[*itset].path + connect[*itset][(chain[*itset].Next)[chain[*itset].cnt]] < min)
        {
            m.clear();
            minnext = (chain[*itset].Next)[chain[*itset].cnt];
            minpre = *itset;
            m[minpre] = minnext;
            min =  chain[*itset].path + connect[*itset][(chain[*itset].Next)[chain[*itset].cnt]] ;
        }
        
        //calculate the next node in the vis set
        itset++;
    }
    
    map<int,int> :: iterator itt = m.begin();
    
    //put the minimal distance nodes into the visited set and refresh their information
    while(itt != m.end())
    {
        vis.insert(itt->second);
        chain[itt->second].path = min;
        chain[itt->second].pre.push_back(itt->first);
        itt++;
    }
    itt--;
    
    //if the target node has been found the procedure can be terminated
    if(itt->second == target) return;
    
    //find the next minimal distance node
    minpath();
}

//value is set to store the minimal distance paths
vector<vector<int> > value;

//the function is to find the minimal distance paths reversely
void bikereverse(int st,vector<int> ppath)
{
    //ppath is a particular minimal distance path
    ppath.push_back(st);
    
    //if st == 0, the completed path has been founde
    if(st == 0)
    {
        value.push_back(ppath);
        return;
    }
    
    for(int i=0;i<chain[st].pre.size();i++)
    {
        bikereverse(chain[st].pre[i],ppath);
    }
    
}


//the function is to find the minimal carry bike path in the paths in vector value
void findans()
{
    int ans[value.size()][2];
    
    //tempcarry stores till now how many bikes we have to carry in the beginning
    //tempback stores till now how many bikes we have to bring back
    int tempcarry=0,tempback=0;
    for(int i=0;i<value.size();i++)
    {
        //initialize the varible tempcarry, tempback to 0
        tempcarry = 0;
        tempback = 0;
        
        //the following procedure is to simulate the procedure to see how many bikes we will carry
        for(int j=value[i].size()-2;j>=0;j--)
        {
            if(chain[value[i][j]].bike < maxbike/2)
            {
                //if the number of bikes is less, we should replenish it
                if(tempback >= maxbike/2 - chain[value[i][j]].bike)
                {
                    //if we have enough bikes,we can replenish without increasing the carrybike
                    tempback = tempback - (maxbike/2 - chain[value[i][j]].bike);
                }else
                {
                    //otherwise we must carry these bikes in the beginning
                    tempcarry += maxbike/2 - chain[value[i][j]].bike - tempback;
                    tempback = 0;
                }
            }else
            {
                //if the bikes are greater,we must bring them back
                tempback += chain[value[i][j]].bike - maxbike/2;
            }
        }
        
        //store the tempcarry and tempback of this path in the vector ans
        ans[i][0] = tempcarry;
        ans[i][1] = tempback;
    }
  
    //the following procedure is to find the path in which we can carry the least bike and the minimal bikes we must bring back
    int Min = INT_MAX,Min2 = INT_MAX;
    int ANS;
    for(int i=0;i<value.size();i++)
    {
        if(ans[i][0] < Min) Min = ans[i][0];
    }
    for(int i=0;i<value.size();i++)
    {
        if(ans[i][0] == Min)
        {
            if(ans[i][1] < Min2){
                Min2 = ans[i][1];
                ANS = i;
            }
        }
    }
    
    //then print out the answer
    printf("%d ",ans[ANS][0]);
    printf("0");
    for(int j = value[ANS].size()-2;j>=0;j--)
    {
        printf("->%d",value[ANS][j]);
    }
    printf(" %d",ans[ANS][1]);
    
}


int main(int argc, const char * argv[]) {
    
    // read the input data
    Read_Data();
    
    //find the minimal distance paths
    minpath();
    
    vector<int> ppath;
    //restore the paths explicitly
    bikereverse(target,ppath);
    
    //find the optimal path among the minimal distance paths and print the answer
    findans();
    
    return 0;
}

后记

这是Data Structure课程的第二个大程。相比前一个的POW思考量问题已经提高了不少。之后我将陆续整理DS课程和ADS课程的其他大程一并放上来,以望共勉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值