题解 城市交通(附数据)

另一道

题面

某城市 有N(1<=N<=50)个街区,某些街区由公共汽车线路相连,如在图1中,街区1,2有一条公共汽车线路相连,且由街区1至街区2的时间为34分钟。由于街区与街区之间的距离较近,与等车时间相比可忽略不记,所以这个时间为两趟公共汽车的间隔时间,即平均的等车时间。由街区1至街区5的最快走法为1-3-5,总时间为44分钟。现在市政府为了提高城市交通质量,决定加开M(1<=M<=10)条公共汽车线路。若在某两个街区A,B之间加开线路(前提是A、B之间必须已有线路),则从A到B的旅行时间缩小为原来的一半(距离未变,只是等车的时间缩短了一半)。例如,若在1,2之间加开一条线路,则时间变为17分钟,加开两条线路,时间变为8.5分钟,以此类推。所有的线路都是环路,即如果由1至2的时间变为17分钟,则由2至1的时间也变为17分钟。
求加开某些线路,能使由城市1至城市N的时间最少。例如,在图1中,如果M=2,则改变1-3,3-5的线路,总的时间可以减少为22分钟。
图一:

input:
5 2
0 34 24 0 0
34 0 10 12 0
24 10 0 16 20
0 12 16 0 30
0 0 20 30 0

output:
22.00
1 3
3 5
Dijkstra+dp

#include<bits/stdc++.h>
using namespace std;
int n,m;
double dist[51][11];
struct edge
{
	int to;
	double dis;
	int N;
};
struct node
{
	double dis;
	int pos,N;
	int st[11];
	int en[11];
	bool operator < (const node &x)const
	{
		return x.dis<dis;
	}
};
vector<edge>a[510];
int ans1[11],ans2[11];
void Dijkstra(int x)
{
	priority_queue<node>q;
	for(int i=0;i<=m;i++)
	{
		node sta;
		sta.dis=0;
		sta.pos=x;
		sta.N=i;
		dist[x][i]=0;
		q.push(sta);
	}
	while(!q.empty())
	{
		node T=q.top();
		q.pop();
		int now=T.pos;
		for(int i=0;i<a[now].size();i++)
		{
			if(a[now][i].N+T.N>m)
			{
				continue;
			}
			if(dist[a[now][i].to][T.N+a[now][i].N]>dist[now][T.N]+a[now][i].dis)
			{
				dist[a[now][i].to][T.N+a[now][i].N]=dist[now][T.N]+a[now][i].dis;
				for(int j=T.N+1;j<=T.N+a[now][i].N;j++)
				{
					T.st[j]=now;
					T.en[j]=a[now][i].to;
				}
				node tmp;
				tmp.dis=dist[a[now][i].to][T.N+a[now][i].N];
				tmp.pos=a[now][i].to;
				tmp.N=T.N+a[now][i].N;
				for(int j=1;j<=m;j++)
				{
					tmp.st[j]=T.st[j];
					tmp.en[j]=T.en[j];
				}
				if(tmp.pos==n&&tmp.N==m)
				{
					for(int k=1;k<=m;k++)
					{
						ans1[k]=tmp.st[k];
						ans2[k]=tmp.en[k];
					}
				}
				q.push(tmp);
			}
		}
	}
}
int main()
{
	//freopen("City.in","r",stdin);
	//freopen("City.out","w",stdout);
	cin>>n>>m;
	double ip1;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>ip1;
			if(ip1)
			{
				for(int k=1,js=0;js<=m;k*=2,js++)
				{
					a[i].push_back((edge){j,ip1/k,js});
				}
			}
		}
		
	}
	for(int i=0;i<=50;i++)
	{
		for(int j=0;j<=10;j++)
		{
			dist[i][j]=2147483647;
		}
	}
	Dijkstra(1);
	printf("%.2lf\n",dist[n][m]);
	for(int i=1;i<=m;i++)
	{
		cout<<ans1[i]<<" "<<ans2[i]<<endl;
	}
}

数据

posted @ 2019-06-09 17:23  G_A_TS  阅读(603)  评论(0编辑  收藏  举报