栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

2022“杭电杯”中国大学生算法设计超级联赛(4)1005 (Problem 7178) Link with Level Editor II(矩阵乘法+双指针)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

2022“杭电杯”中国大学生算法设计超级联赛(4)1005 (Problem 7178) Link with Level Editor II(矩阵乘法+双指针)

2022“杭电杯”中国大学生算法设计超级联赛(4)1005 (Problem 7178) Link with Level Editor II(矩阵乘法+双指针) 题目链接:Link with Level Editor II 题意:

给定 n n n个图,每个图有 m m m个点, l l l条有向边,选出一段最长的连续的世界,使得满足:
初始在第一个图的点 1 1 1,每次操作可以在当前图选择一条和当前点相连的边走向另一个点或者呆在该点,每次操作后都会从该世界传送到下一个世界对应点,在最后一个世界时恰好到达点 m m m的方案数不超过 k k k种.

题解:

发现 m m m很小,我们可以使用矩阵来储存图,这样我们就可以通过矩阵乘法来求得一段区间内从点 1 1 1到 m m m的路径数(离散数学里的,不知道的可以去先学一下,这里不再缀叙),知道了一段区间内的方案数,显然我们可以利用双指针来求最长合法区间,但是发现在确定 r r r后收缩 l l l的过程中的除的部分很麻烦,,我们可以再开一个矩阵数组 b b b,和一个分界线 l i m lim lim, b [ i ] b[i] b[i]表示的即为 a [ i ] a[i] a[i]到 a [ l i m ] a[lim] a[lim]的累乘和,用 b a s e base base表示 a [ l i m + 1 ] a[lim+1] a[lim+1]到 a [ r ] a[r] a[r]的累乘和,这样每次 a [ l ] ∗ b a s e a[l]*base a[l]∗base即为 a [ l ] a[l] a[l]到 a [ r ] a[r] a[r]的累乘和,这时判断下方案数是否超过k来确定双指针走向即可。

具体实现和细节参考代码注释:

ll n,m,k;
struct square{
	ll v[22][22];
	square(int x=0){
		memset(v,0,sizeof(v));
		for(int i=1;i<=m;i++){
			v[i][i]=x;
		}
	}
	square operator *(square q){
		square ans;
		for(int i=1;i<=m;i++){
			for(int j=1;j<=m;j++){
				for(int k=1;k<=m;k++){
					ans.v[i][j]=ans.v[i][j]+v[i][k]*q.v[k][j];
					if(ans.v[i][j]>1e9){//多次累乘可能越界,过大就处理一下
						ans.v[i][j]=1e9;
					}
				}
			}
		}
		return ans;
	}
	void print(){
		for(int i=1;i<=m;i++){
			for(int j=1;j<=m;j++){
				cout<//判断当前方案数是否超出k
	ll ans=0;
	for(int i=1;i<=m;i++){
		ans+=x.v[1][i]*y.v[i][m];
		if(ans>k){
			return 0;
		}
	}
	return 1;
}
int main(){
/*cout<>t;
	while(t--){
		cin>>n>>m>>k;
		for(int i=1;i<=n;i++){
			int l;
			cin>>l;
			a[i]=1;
			for(int j=1;j<=l;j++){
				int u,v;
				cin>>u>>v;
				a[i].v[u][v]=1;
			}
		}
		int ans=0;
		b[0].v[1][m]=inf;//初始化
		square base=1;
		for(int l=0,lim=0,r=1;r<=n;r++){
			base=base*a[r];//储存a[lim+1]-a[r]的累乘和
			while(!check(b[l],base)){//方案数过多,开始缩小区间,查找当前人对应的l
			//根据base,和b[i]的含义,b[l]*base即为a[l]-a[r]的累乘和
				l++;
				if(l>lim){//l超过lim了,此时lim后面的b还没有定义,需要更新lim和对应的b
					base=1;
					b[r]=a[r];//b[i]储存的是a[i]-a[lim]间的累乘和,
					for(int i=r-1;i>lim;i--){
						b[i]=a[i]*b[i+1];
					}
					lim=r;
				}
			}
			ans=max(ans,r-l+1);//更新答案
		}
		cout<
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1029113.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号