前言
在最近整理大学前两年学的内容时,突然发现了这个初级数据结构程序,主要是根据边的权重来给出最优解。现发布在这里,希望可以给学习的同袍们一点帮助。
题目要求
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课程的其他大程一并放上来,以望共勉。