习题11-7 UVa 10801 Lift Hopping SPFA最短路

题意分析:

从0层开始,一共有n台电梯供你到达目的地k层。每台电梯往上走一层都要消耗t[i]的时间,并且电梯只能在特定的楼层停下,换乘电梯要花费60s的时间,而且呢,你不能用楼梯上楼,只能搭电梯。。。。(hentai!)问:最快到达楼层k的时间是多少?不能到达就输出IMPOSSIBLE

解题思路:

这题技巧就是体现在建图上,用邻接矩阵更好,图建好了,用dijkstra或spfa跑一遍就行了。

具体建图就是用G[i][j]代表从楼层i到楼层j的最小距离。这里不考虑换乘,先这样把图建好。

对于换乘,我们在dijkstra更新节点的时候使用。具体为:dist[y] = min(dist[y], d[x] + G[x][y] + 60);

这里更新时加上60s的具体理由在于:这里我们默认第一次进电梯算是换乘,所以加上60s。这样不管是一路搭到底(每个dist[i]都加60,一起比较起来没有影响),还是有换乘(本来就该加60s嘛)。都不会影响。

这样在计算最终结果时,减去60就是最终的结果了(因为默认了第一次进入电梯算换乘)。

#include<bits/stdc++.h>
const int maxn=105;
const int INF=0x3f3f3f3f;
typedef long long LL;
using namespace std;
int G[maxn][maxn];
int dist[maxn];
int vis[maxn];
int sp[maxn];
int N,K;
int a[maxn];
struct Edge
{
	int e,w;
	Edge(){}
	Edge(int _e,int _w):e(_e),w(_w){}
	bool operator <(const Edge &v)const{
		return w>v.w;
	}
};
void graph(int k,int count)
{
	for(int i=0;i<count;i++)
	{
		for(int j=i+1;j<count;j++)
		{
			int s=a[i];
			int e=a[j];
			int w=(e-s)*sp[k];
			if(G[s][e]>w) G[s][e]=G[e][s]=w;
		}
	}
}
void input()
{
	for(int i=0;i<N;i++) cin>>sp[i];
	string line;
	getchar();
	for(int i=0;i<N;i++)
	{
		int x,count=0;
		/*
		char c;
		do{
			cin>>a[count++];
		}while(getchar()!='\n'); 
		*/
		getline(cin,line);
		stringstream ss(line);
		while(ss>>x)
		{
			a[count++]=x;
		}
        graph(i,count);
	}
}

void spfa(int S)
{
	memset(vis,0,sizeof(vis));
	memset(dist,INF,sizeof(dist));
	queue<int>q;
	dist[S]=0;
	vis[S]=1;
	q.push(S);
	while(!q.empty())
	{
		int s=q.front();q.pop();
		vis[s]=0;
		for(int i=0;i<=99;i++)
		{
			if(dist[i]>dist[s]+G[s][i]+60)
			{
				dist[i]=dist[s]+G[s][i]+60;
				if(!vis[i])
				{
					vis[i]=1;
					q.push(i);
				}
			}
		}
	}
	if(dist[K]==INF) puts("IMPOSSIBLE");
    else cout<<max(0,dist[K]-60)<<endl; //小心目标楼层为0的情况 
}

void dij(int S)
{
	memset(vis,0,sizeof(vis));
	memset(dist,INF,sizeof(dist));
	priority_queue<Edge> q;
	q.push(Edge(S,0));
	dist[S]=0;
	while(!q.empty())
	{
		int s=q.top().e;q.pop();
		if(vis[s]) continue;
		vis[s]=1;
		for(int i=0;i<=99;i++)
		{
			if(!vis[i]&&dist[i]>dist[s]+G[s][i]+60)
			{
				dist[i]=dist[s]+G[s][i]+60;
				q.push(Edge(i,dist[i]));
			}
		}
	}
	if(dist[K]==INF) puts("IMPOSSIBLE");
    else cout<<max(0,dist[K]-60)<<endl; 
}

int main()
{
//	freopen("E:\\ACM\\test.txt","r",stdin);
	while(cin>>N>>K)
	{
		memset(G,INF,sizeof(G));
		
		input();
//		spfa(0);
		dij(0);
	}
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值