其他分享
首页 > 其他分享> > [HNOI2002]公交车路线

[HNOI2002]公交车路线

作者:互联网

[HNOI2002]公交车路线

注:今天做到的有点意思的题目。

题意简述

有\(8\)个站点,从\(A\) 出发一共走\(n\) 步到\(E\)(中途不可经过\(E\)),问一共有多少种走法?

图:

思路一:矩阵(假弗洛伊德)

这个题感觉和矩阵半毛钱关系都没有,那可能用矩阵?

不过不慌哈,让我们细细道来。

我们设\(dp[i][j]\) 为从\(i\)到 \(j\)有\(m\)种方式。

\[\notag 当走每一步时,都有以下转移方程:\\ dp[i][j] = \sum\limits _{k=1}^{n} dp[i][k]*dp[k][j] \]

这是显然的,因为此时从 \(i\) 到 \(k\) 有 \(dp[i][k]\) 种方式,从 \(k\) 到 \(j\) 有 \(dp[k][j]\) 种方式,乘法原理一下,就可以得到以上方程。

题外话:不知各位是否有一种熟悉的感觉,看看以下式子(弗洛伊德):

\[\notag dis[i][j] = \sum\limits _{k=1}^{n} \min(dis[i][k]+dis[k][j],dis[i][j]) \]

嘿嘿,好了回到这个题。

上面这个式子又和矩阵有什么关系呢?

让我们先看看矩阵乘法的表达式:

\[\notag A(n*n),B(n*n)\\ C=AB\\ C[i][j]=\sum\limits _{k=1}^{n} A[i][k]*B[k][j] \]

emm....不能说一模一样吧,但可以说完全一致。

所以结果就显然了。

但是!还没有完,我们只有转移方程但没有最开始的矩阵,就像数学归纳法一样只有\(n>=2\)时成立,但\(n=1\)时不成立又有什么用呢?

以下依据 \(dp[i][j]\) 为从\(i\)到 \(j\)的方式给出基础矩阵:

\[\notag \begin{bmatrix} Z&A&B&C&D&E&F&G&H\\ A&0&1&0&0&0&0&0&1\\ B&1&0&1&0&0&0&0&0\\ C&0&1&0&1&0&0&0&0\\ D&0&0&1&0&1&0&0&0\\ E&0&0&0&0&0&0&0&0\\ F&0&0&0&0&1&0&1&0\\ G&0&0&0&0&0&1&0&1\\ H&1&0&0&0&0&0&1&0\\ \end{bmatrix} \]

解释:行表示出发点,列表示到达到点,其中由于不可以经过\(E\)所以\(E\)所在行为\(0\)。

时间复杂度

\(O(8^2\log n)\)

CODE

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn = 5e5+32;
ll int_maxn=1e9;
ll ll_maxn=1e18;
inline ll read_int(){
    ll a=0,f=0,g=getchar();
    while(g<'0'||g>'9'){if(g=='-') f=1;g=getchar();}
    while('0'<=g&&g<='9') a=a*10+g-'0',g=getchar();
    return f ? -a : a;
}
inline void write(ll s,bool f,int cnt=0){
    ll top=0,a[40];
    if(s<0) s=-s,putchar('-');
    while(s) a[++top]=s%10,s/=10;
    if(top==0) a[++top]=0;
    while(top) putchar(a[top]+'0'),top--;
    if(f) putchar('\n');
    while(cnt--) putchar(' ');
}

const int maxm=10;

int lin[9][9]={
//    a b c d e f g h
	0,0,0,0,0,0,0,0,0,
	0,0,1,0,0,0,0,0,1,
	0,1,0,1,0,0,0,0,0,
	0,0,1,0,1,0,0,0,0,
	0,0,0,1,0,1,0,0,0,
	0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,1,0,1,0,
	0,0,0,0,0,0,1,0,1,
	0,1,0,0,0,0,0,1,0,
};

int mod=1000;

struct Matrix{
	ll n,m;
	ll matrix[maxm][maxm];
	inline void clear(){n=m=0,memset(matrix,0,sizeof matrix);}
	inline void jc(ll M){
		clear();
		n=m=M;
		for(ll i=1;i<=n;i++) matrix[i][i]=1;
	}
	Matrix operator * (Matrix a)const{
		Matrix b;
		b.clear();
		b.n=n,b.m=a.m;
		for(ll i=1;i<=b.n;i++){
			for(ll e=1;e<=b.m;e++){
				for(ll k=1;k<=m;k++){
					b.matrix[i][e]+=matrix[i][k]*a.matrix[k][e];
					b.matrix[i][e]%=mod;
				}
			}
		}
		return b;
	}
	friend inline Matrix qpow(Matrix a,ll C){
		Matrix base;
		base.jc(a.n);
		while(C){
			if(C&1) base=base*a;
			a=a*a,C>>=1;
		}
		return base;
	}
	inline void write_(bool a){
		if(a) write(n,0),putchar(' '),write(m,1);
		for(ll i=1;i<=n;i++){
			for(ll e=1;e<=m;e++){
				write(matrix[i][e],0),putchar(' ');
			}
			puts("");
		}
	}
	inline void td(){
		clear();
		n=m=8;
		for(int i=1;i<=8;i++){
			for(int e=1;e<=8;e++){
				matrix[i][e]=lin[i][e];
			}
		}
	}
	inline int add_m(int cnt){
		ll ans=0;
		for(int i=1;i<=n;i++){
			ans+=matrix[i][cnt];
			ans%=mod;
		}
		return ans;
	}
};

inline void read(){
	int n=read_int();
	Matrix A;
	A.td();
	A=qpow(A,n);
	write(A.matrix[1][5],1);
}

int main (){
	read();
}

思路二:DP

注:转自题解

时间复杂有点高(相对于上一个来说):\(O(n)\)

我们把\(E\)去掉,这个系统分成了以\(A\)为中心的完全对称的列。

我们记\(dp[i][j]\)表示第\(i\)站在\(j\)次乘坐后到达的方案数。

因为每次只能从相邻的站到达,那么第\(N\)次到达\(E\)的方案数等于第\(N-1\)次到达\(D\)和\(F\)的方案数。

以此类推\(dp[i][j]=dp[i-1][j-1]+dp[i+1][j-1]\) 这里的\(i-1\)\(,\)i+1$表示相邻的站。

之前说过以\(A\)为中心完全对称,所以\(D\)和\(F\),\(C\)和\(G\)......的方案数完全相同,只需算一边。

仔细观察,每个状态只与上一个状态有关,因此可以压位为\(dp[4][2]\)

CODE

#include<iostream>
using namespace std;
int dp[4][2];              //具体含义如上所述
int main()
{
    fill(dp[0],dp[0]+4*2,0);
    dp[0][0]=1;
    int N,pos=0;
    cni>>N;
    for(int k=1;k<N;k++)
    {
        pos=pos^1;
        dp[0][pos]=2*dp[1][pos^1]%1000;        //A处的方案等于两边的方案相加,由于相等只算一边的*2
        dp[1][pos]=(dp[0][pos^1]+dp[2][pos^1])%1000;
        dp[2][pos]=(dp[1][pos^1]+dp[3][pos^1])%1000;
        dp[3][pos]=dp[2][pos^1];                     //D只能由C来
    }
    cout<<2*dp[3][pos]%1000<<endl;            //E由D和F来
    return 0;        
}


标签:公交车,int,ll,矩阵,notag,路线,HNOI2002,dp,dis
来源: https://www.cnblogs.com/LQX-OI/p/16391467.html