洛谷p1613 跑路

大致题意:给一张有向图(存在自环),每条边权均为1,现在有一人要从1号结点走到n号结点,但是这个人有一个神奇的瞬移机器,这个机器走 2 k 2^k 2k( k k k为自然数)花费的时间都为1,问从起点到终点的最小花费时间。
思路如下:
step 1.我们可以处理出所有的从一个点到达另一个点的距离可以为 2 k 2^k 2k的路径,并把这两个点之间连一条权值为1的边。
step 2.在我们新得到的图上运行最短路算法,求出从起点到达终点花费的最少时间。

下面我们来看看如何处理step 1:

状态表示:用 f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]记录能否通过 2 k 2^k 2k的距离从 i i i到达 j j j.
转移方程 i f ( f [ i ] [ u ] [ k − 1 ] if(f[i][u][k-1] if(f[i][u][k1]&& f [ u ] [ j ] [ k − 1 ] ) f[u][j][k-1]) f[u][j][k1]) f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]为真。
需要注意:因为题意已经给出任意边的边权均为1,则可以用反证法证明:若 f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]为真,则一定存在中间结点使得 f [ i ] [ u ] [ k − 1 ] f[i][u][k-1] f[i][u][k1]&& f [ u ] [ j ] [ k − 1 ] f[u][j][k-1] f[u][j][k1]为真。

代码如下:

#include<cstring>
#include<iostream>
using namespace std;
const int N = 100, M = 20000;
const int K = 35;
int f[N][N][K];
int g[N][N];
int n,m;
int main()
{
	memset(f,0x3f,sizeof f);
	memset(g,0x3f,sizeof g);
	cin>>n>>m;
	for(int i=1;i<=m;++i)
	{
		int a,b;
		cin>>a>>b;
		f[a][b][0]=1;
		g[a][b]=1;
	}
	for(int u=1;u<=32;++u)
		for(int k=1;k<=n;++k)
			for(int i=1;i<=n;++i)
				for(int j=1;j<=n;++j)
					if(f[i][k][u-1]==1&&f[k][j][u-1]==1)
					{
						f[i][j][u]=1;
						g[i][j]=1;
					}

	for(int k=1;k<=n;++k)
		for(int i=1;i<=n;++i)
			for(int j=1;j<=n;++j)
				g[i][j]=min(g[i][k]+g[k][j],g[i][j]);
	
	cout<<g[1][n]<<endl;
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值