1018. Public Bike Management (30) @ PAT (Advanced Level) Practise

20 篇文章 0 订阅


对Dijkstra算法的复习

求解从s点到t点的最短路径

#include<iostream>
#include<vector>

using namespace std;

#define INF 0x6FFFFFFF 

struct Edge
{
	int v,dist;
	Edge(int _v,int _dist):v(_v),dist(_dist){}
};
struct Node
{
	int dist;
	bool visited;
	vector<int> pre;
};

vector<Node> city;
vector<vector<Edge>> G;

int n;//vertexs
int m;//edges

void Dijkstra(int s,int t)
{
	//init
	city.clear();
	city.resize(n+1);

	for(int i=0;i<=n;i++)
	{
		city[i].visited=false;
		city[i].dist=INF;
	}
	city[s].dist=0;
	
	while(true)
	{
		//find min
		int index=-1;
		int mindist=INF;
		for(int i=0;i<=n;i++)
		{
			if(city[i].dist<mindist && !city[i].visited)
			{
				index=i;
				mindist=city[i].dist;
			}
		}
		if(index==-1)
			return ;
		city[index].visited=true;

		//scan the neighborhood
		for(int i=0;i<G[index].size();i++)
		{
			int v=G[index][i].v;
			if(!city[v].visited)
			{
				if(city[v].dist>(city[index].dist+G[index][i].dist))
				{
					city[v].pre.clear();
					city[v].pre.push_back(index);
					city[v].dist=city[index].dist+G[index][i].dist;
				}
				else if(city[v].dist==(city[index].dist+G[index][i].dist))
				{
					city[v].pre.push_back(index);
				}
			}
		}
	}

	return ;
}

int main()
{
	cin>>n>>m;
	int a,b,c;
	G.clear();
	G.resize(n+1);
	for(int i=0;i<m;i++)
	{
		cin>>a>>b>>c;
		G[a].push_back(Edge(b,c));
		G[b].push_back(Edge(a,c));
	}
	while(true)
	{
		int s,t;
		cin>>s>>t;
		if(s==-1 || t==-1)
			break;
		Dijkstra(s,t);
		cout<<"smallest dist:"<<city[t].dist<<endl;
		for(int i=0;i<city.size();i++)
		{
			cout<<"vertex["<<i<<"]:"<<city[i].dist<<"  ";
			for(int j=0;j<city[i].pre.size();j++)
			{
				cout<<city[i].pre[j]<<" ";
			}
			cout<<endl;
		}
	}
	
	return 0;
}

2个测试用的图:

6 9
0 1 7
0 2 9
0 5 14
1 2 10
1 3 15
2 3 11
2 5 2
3 4 6
4 5 9


==============

4 5
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1
==============
8 9
0 1 1
0 2 1
1 3 1
1 4 1
2 5 1
2 6 1
3 7 1
4 7 1
5 6 1


复习一下DFS

ps.关于DFS遍历最短路径,在下面一小节中

#include<iostream>
#include<vector>

using namespace std;

#define INF 0x6FFFFFFF 

struct Edge
{
    int v,dist;
    Edge(int _v,int _dist):v(_v),dist(_dist){}
};
struct Node
{
    int dist;
    bool visited;
    vector<int> pre;
};

vector<Node> city;
vector<vector<Edge>> G;

vector<int> DFSPath;
int n;//vertexs
int m;//edges

void Dijkstra(int s,int t)
{
    //init
    city.clear();
    city.resize(n+1);

    for(int i=0;i<=n;i++)
    {
        city[i].visited=false;
        city[i].dist=INF;
    }
    city[s].dist=0;
    
    while(true)
    {
        //find min
        int index=-1;
        int mindist=INF;
        for(int i=0;i<=n;i++)
        {
            if(city[i].dist<mindist && !city[i].visited)
            {
                index=i;
                mindist=city[i].dist;
            }
        }
        if(index==-1)
            return ;
        city[index].visited=true;

        //scan the neighborhood
        for(int i=0;i<G[index].size();i++)
        {
            int v=G[index][i].v;
            if(!city[v].visited)
            {
                if(city[v].dist>(city[index].dist+G[index][i].dist))
                {
                    city[v].pre.clear();
                    city[v].pre.push_back(index);
                    city[v].dist=city[index].dist+G[index][i].dist;
                }
                else if(city[v].dist==(city[index].dist+G[index][i].dist))
                {
                    city[v].pre.push_back(index);
                }
            }
        }
    }

    return ;
}

void DFS(int s,int t)
{
    city[s].visited=true;
    DFSPath.push_back(s);
    for(int i=0;i<G[s].size();i++)
    {
        int v=G[s][i].v;
        if(!city[v].visited)
        {
            DFS(v,t);
        }
    }
    return;
}
int main()
{
    cin>>n>>m;
    int a,b,c;
    G.clear();
    G.resize(n+1);
    for(int i=0;i<m;i++)
    {
        cin>>a>>b>>c;
        G[a].push_back(Edge(b,c));
        G[b].push_back(Edge(a,c));
    }
    while(true)
    {
        int s,t;
        cin>>s>>t;
        if(s==-1 || t==-1)
            break;

        //Dijkstra
        Dijkstra(s,t);
        cout<<"smallest dist:"<<city[t].dist<<endl;
        for(int i=0;i<city.size();i++)
        {
            cout<<"vertex["<<i<<"]:"<<city[i].dist<<"  ";
            for(int j=0;j<city[i].pre.size();j++)
            {
                cout<<city[i].pre[j]<<" ";
            }
            cout<<endl;
        }

        //DFS
        //init
        for(int i=0;i<city.size();i++)
            city[i].visited=false;
        
        DFS(s,t);
        //display the path
        for(int j=0;j<DFSPath.size();j++)
            cout<<DFSPath[j]<<" " ;
        cout<<endl;
    }
    
    return 0;
}

A1018的解

整体思路:首先用Dijkstra算法找到所有最短路径,并在每个节点上记录最短路径时的所有前缀。然后从目标点到源(t->s)按每个结点记录的前缀向量表深度优先遍历(DFS,findBestPath函数)出所有最短的路径。对每条最短路径计算需要带出的车数(TakeTo)和带回的车数(TakeBack),与最佳路径的这两个值比较即可。

关于DFS遍历最短路径

DFS(s,t)
	push(s)
	foreach v in neighborhood of s
		if v==t
			push(v)
			continue
		else
			DFS(v,t)
	pop()
end

A1018代码:
#include<iostream>
#include<vector>

using namespace std;

#define INF 0x6FFFFFFF 

struct Edge
{
    int v,dist;
    Edge(int _v,int _dist):v(_v),dist(_dist){}
};
struct Node
{
    int dist;
    bool visited;
	int c;
    vector<int> pre;
};

vector<Node> city;
vector<vector<Edge>> G;

vector<int>bPath;//best path
vector<int>cPath;//current path
int bTakeTo=0,bTakeBack=0,cTakeTo=0,cTakeBack=0;
vector<int>::reverse_iterator rit;
//vector<int> DFSPath;
int cmax;//max capacity of each station
int n;//vertexs
int sp;//target station
int m;//edges
int hfull;

void Dijkstra(int s,int t)
{
    for(int i=0;i<=n;i++)
    {
        city[i].visited=false;
        city[i].dist=INF;
    }
    city[s].dist=0;
    
    while(true)
    {
        //find min
        int index=-1;
        int mindist=INF;
        for(int i=0;i<=n;i++)
        {
            if(city[i].dist<mindist && !city[i].visited)
            {
                index=i;
                mindist=city[i].dist;
            }
        }
        if(index==-1)
            return ;
        city[index].visited=true;

        //scan the neighborhood
        for(int i=0;i<G[index].size();i++)
        {
            int v=G[index][i].v;
            if(!city[v].visited)
            {
                if(city[v].dist>(city[index].dist+G[index][i].dist))
                {
                    city[v].pre.clear();
                    city[v].pre.push_back(index);
                    city[v].dist=city[index].dist+G[index][i].dist;
                }
                else if(city[v].dist==(city[index].dist+G[index][i].dist))
                {
                    city[v].pre.push_back(index);
                }
            }
        }
    }
    return ;
}
void findBestPath(int s,int t)
{
	cPath.push_back(t);
	for(int i=0;i<city[t].pre.size();i++)
	{
		int v=city[t].pre[i];
		if(v!=s)
		{
			findBestPath(s,v);
		}
		else
		{
			if(bPath.empty())
			{
				//update best path info
				bPath.assign(cPath.begin(),cPath.end());
				for(rit=bPath.rbegin();rit!=bPath.rend();rit++)
				{
					if(city[*rit].c<hfull)
					{
						if(bTakeBack>hfull-city[*rit].c)
						{
							bTakeBack-=hfull-city[*rit].c;
						}
						else if(bTakeBack>0)
						{
							bTakeTo+=hfull-city[*rit].c-bTakeBack;
							bTakeBack=0;
						}
						else
						{
							bTakeTo+=hfull-city[*rit].c;
						}
					}
					else if(city[*rit].c>hfull)
					{
						bTakeBack+=city[*rit].c-hfull;
					}
				}
								
			}
			else
			{
				//calculate cTakeTo & cTakeBack
				for(rit=cPath.rbegin();rit!=cPath.rend();rit++)
				{
					if(city[*rit].c<hfull)
					{
						if(cTakeBack>hfull-city[*rit].c)
							cTakeBack-=hfull-city[*rit].c;
						else if(cTakeBack>0)
						{
							cTakeTo+=hfull-city[*rit].c-cTakeBack;
							cTakeBack=0;
						}
						else
							cTakeTo+=hfull-city[*rit].c;
					}
					else if(city[*rit].c>hfull)
					{
						cTakeBack+=city[*rit].c-hfull;
					}
				}
				//compare cPath & bPath
				if(bTakeTo>cTakeTo || (bTakeTo==cTakeTo && bTakeBack>cTakeBack))
				{
					bTakeTo=cTakeTo;
					bTakeBack=cTakeBack;
					bPath.assign(cPath.begin(),cPath.end());

				}
			}
			//clear current path info
				continue;
				cTakeTo=0;
				cTakeBack=0;
		}

	}
	cPath.pop_back();
	cTakeTo=0;
	cTakeBack=0;
	return ;
}

int main()
{
    cin>>cmax>>n>>sp>>m;
	hfull=cmax/2;
	//init
    city.clear();
    city.resize(n+1);
	for(int i=1;i<=n;i++)
		cin>>city[i].c;
    int a,b,c;
    G.clear();
    G.resize(n+1);
    for(int i=0;i<m;i++)
    {
        cin>>a>>b>>c;
        G[a].push_back(Edge(b,c));
        G[b].push_back(Edge(a,c));
    }
        int s=0,t=sp;
        //Dijkstra
        Dijkstra(s,t);
		
		cPath.clear();
		bPath.clear();
		//DFS
		findBestPath(s,t);
		cout<<bTakeTo<<" ";
		cout<<s<<"->";
		for(int i=bPath.size()-1;i>0;i--)
			cout<<bPath[i]<<"->";
		cout<<t<<" ";		
		cout<<bTakeBack;
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值