首页 > 其他分享 >Luogu P1613 跑路 题解 [ 蓝 ] [ 倍增 ] [ Floyd 最短路 ] [ 状压 dp ]

Luogu P1613 跑路 题解 [ 蓝 ] [ 倍增 ] [ Floyd 最短路 ] [ 状压 dp ]

时间:2024-08-01 16:29:55浏览次数:6  
标签:int 题解 状压 55 Floyd Luogu 倍增 dp

跑路:绝佳倍增好题,思路是化 \(2^k\) 为 \(1\) ,倍增起预处理作用。

最近不知道是撞了什么运,前一脚看的是绿题,写完之后交一发,发现直接被 lxl 升蓝了,血赚。

思路:Floyd

首先观察到每次走 \(2^k\) 的代价为 \(1\) ,我们可以预处理出每次走 \(2^i\) 能到哪些点。

但为了让这题的代码更好实现一些,观察到 \(n\) 较小,只有 \(50\) ,于是就可以定义邻接矩阵,\(g[i][j][k]\) 表示从 \(j\) 走 \(2^i\) 步能否到 \(k\) 点,能到即为 \(1\) 。

于是转移方程就出来了,我们枚举一下中点 \(l\) ,然后:

\[g[i][j][k]=g[i][j][k] | (g[i-1][j][l] \& g[i-1][l][k]) \]

这样我们就求出某个点能否用 \(1\) 的代价到另一个点,化 \(2^k\) 成 \(1\) 了。

接下来就直接建边,跑 Floyd 或者其他乱七八糟的算法求最短路即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
int n,m,f[55][55];
bitset<55>g[70][55];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	//prepare
	for(int i=1;i<=m;i++)
	{
		int u,v;
		cin>>u>>v;
		g[0][u][v]=1;
	}
	for(int i=1;i<=64;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int k=1;k<=n;k++)
			{
				for(int l=1;l<=n;l++)
				{
					g[i][j][k]=g[i][j][k]|(g[i-1][j][l]&g[i-1][l][k]);
				}
			}
		}
	}
	//build graph
	memset(f,0x3f,sizeof(f));
	for(int i=1;i<=n;i++)f[i][i]=0;
	for(int i=0;i<=64;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int k=1;k<=n;k++)
			{
				if(g[i][j][k]==1)f[j][k]=min(f[j][k],1);
			}
		}		
	}
	//Floyd
	for(int k=1;k<=n;k++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
			}
		}
	}
	cout<<f[1][n];
	return 0;
}

思路:状压 dp

口胡一下,和上面的那种方法差不多。

首先用 vector 记录下从点 \(i\) 走 \(2^k\) 步能到哪些点,然后就建出了一张图。

接下来从 \(0\) 的状态开始,层层向外拓展能到达的点,最后拓展到 \(n\) 时 break 掉并输出此时拓展的层数即可。

注意状态用 ll 存,int 开不下。

标签:int,题解,状压,55,Floyd,Luogu,倍增,dp
From: https://www.cnblogs.com/zhr0102/p/18336917

相关文章

  • 题解:CF1015D Walking Between Houses
    题解:CF1015DWalkingBetweenHouses算法模拟,分类讨论分析首先,设每步走的距离为\(t_i\),我们发现\(t_i\)应是满足\(1\let_i\len-1\)的。那么就很容易推出NO的情况:当\(s<k\)时,由于每一步都要至少走一个单位,所以\(k\)次步数肯定用不完,而题目要求恰好\(k\)次;当......
  • CF716B Complete the Word 题解
    CF716BCompletetheWord题解分析首先观察数据范围是\(50000\),可以考虑\(O(n)\)暴力。在字符串中枚举子串开始的位置\(i\),然后再枚举\(i\)到\(i+25\),开个桶统计每个大写字母出现的次数,如果大于\(1\)就直接break。统计完之后剩下的就都是问号了,可以随便填,所以这个子......
  • P3043 [USACO12JAN] Bovine Alliance G 题解
    P3043[USACO12JAN]BovineAllianceG题目传送门思路首先分情况讨论每种联通块的可能,有三种不同的情况会对答案\(ans\)产生不同的贡献。联通块有环如图,因为每条边都有要有归属,所以环上的边只能全都顺时针或逆时针属于某个点,且不在环上的点仅有一种可能。因此该情况对答......
  • 题解:CF687C The Values You Can Make
    CF687CTheValuesYouCanMake题解题目翻译感觉不明不白的(至少我看了几遍没看懂),这里给个较为清晰的题面。题目描述给你\(n\)个硬币,第\(i\)个硬币有一个价值\(c_i\),你需要从中选出一些价值和为\(k\)的硬币组成一个集合,再输出这个集合中硬币可能组成的价值和。算法动......
  • 题解:CF559B Equivalent Strings
    CF559BEquivalentStrings题解题目描述吐槽一下,题目翻译有歧义。思路分析你会发现,当你需要判断字符串\(a,b\)是否等价时,如果长度为偶数,需要继续判断字符串\(a\)拆分的字串。所用知识s.substr(i,j)//在字符串s中,从位置i开始截取长度为j的字串参考代码#include<bits......
  • 题解:CF718A Efim and Strange Grade
    CF718AEfimandStrangeGrade题解算法贪心+模拟思路分析显然,要最优每一次进位就只能五入不能四舍。而且当我们五入时,要取位数最高的。比如说\(1.3535\),我们有两种进位方式,一种是进位成\(1.4\),一种是进位成\(1.354\),显然前者更优。那这道题给的次数有啥用呢?考虑一种“......
  • P10511 方差 题解
    【题目简述】定义一个长度为\(n\)的序列\(a\)的方差为:\(s^2=\frac{1}{n}\sum_{i=1}^n(a_i-\overline{a})^2\)。\(\sum\)为累加求和符号,\(\overline{a}\)为序列\(a\)的平均数。给定\(m\)个形如\([l,r,b]\)的组合,表示\(a_l,a_{l+1},\ldots,a_r\)为\(b\)。给定......
  • 洛谷P2696之慈善的约瑟夫——题解
    洛谷P2696题解[传送锚点](P2696慈善的约瑟夫-洛谷|计算机科学教育新生态(luogu.com.cn))比不过大佬,从蒟蒻做起选择比较水有意思的解法——用队列模拟(还是窝太弱了)正片开始考虑队列模拟,因为每次都是假的剔除,所以我们的目标是找到每回游戏的最终存活者。将不被剔除,......
  • 题解:Pinely Round 4 (Div. 1 + Div. 2) C
    C.AbsoluteZerotimelimitpertest:2secondsmemorylimitpertest:256megabytesinput:standardinputoutput:standardoutputYouaregivenanarray\(a\)of\(n\)integers.Inoneoperation,youwillperformthefollowingtwo-stepmove:Choose......
  • Codeforces 11D A Simple Task 题解 [ 蓝 ] [ 状压 dp ]
    思路不难想,细节比较多。思路观察到\(n\le19\),首先想到状压dp。于是自然地定义\(dp[j][i]\)为:抵达点的状态为\(i\),且此时在点\(j\)时,简单路径的条数。注意这里是简单路径的条数,而不是环的个数,因为环的个数要在dp过程中统计。这里的dp作用就在于求简单路径条数。......