洛谷P2233 【HNOI2002】公交车路线

题目传送门(洛谷)

这道题看起来像是一道数学题(或许也有数学解法),但是再仔细想想也可以想到它的DP解法。先从最简单的DP开始,我们设 f [ i ] [ j ] f[i][j] f[i][j]表示走 i 步到第 j 个点的方案数,不难看出 f [ i ] [ j ] = f [ i − 1 ] [ j − 1 ] + f [ i − 1 ] [ j + 1 ] f[ i ] [ j ]=f[ i-1 ] [ j-1 ]+f[ i-1 ] [ j+1 ] f[i][j]=f[i1][j1]+f[i1][j+1],也就是走 i-1 步到 j 节点两侧的节点的方案数之和。于是转移也就推出来了,初始化令 f [ 1 ] [ 1 ] = 1 f[1][1]=1 f[1][1]=1,即一开始在A的方案数为1,然后递推就好。

但是这样还做不了,因为n可以到1e7,如果开一个有一维是1e7的数组肯定会MLE。我们再观察一下我们的转移方程,会发现对于每组 f [ i ] f[ i ] f[i],它的大小只与上一步也就是 f [ i − 1 ] f[ i-1 ] f[i1]有关,所以这道题可以用滚动数组优化,滚过之后第一维只需要开到2就行,完美的解决了MLE问题。

其实到这里这道题应该就可以A掉了,但是它还可以再优化。我们可以看出来这道题有对称性,也就是走x步到B的方案数和H相同,C和G相同,D和F相同。所以我们只需要记录AE连线一侧的方案数,最后输出的时候乘以二即可,这样可以节省一半的时间和空间。

还有一些具体的转移细节在代码的注释里。

下面贴上本蒟蒻丑陋的代码

#include<iostream>
#include<cstdio>
using namespace std;
const int mod=1000;
int n,f[2][5];
int main()
{
	scanf("%d",&n);
	f[1][1]=1;//初始化 
	for(int i=2;i<=n;i++)
	{
		int k=i%2;
		f[k][1]=2*f[k^1][2]%mod;//点A的方案数来自B和H,只需要其中一个乘2就好 
		f[k][2]=(f[k^1][1]+f[k^1][3])%mod;//点B的方案数来自A和C 
		f[k][3]=(f[k^1][2]+f[k^1][4])%mod;//点C的方案数来自B和D 
		f[k][4]=f[k^1][3];//点D的方案数来自C,因为走到E之后就不会再走了,所以没有来自E的状态转移过来 
	}
	printf("%d\n",2*f[n%2][4]%mod);//答案就是到D的方案数乘2 
	return 0;
}

PS:这道题似乎可以矩阵乘法加速,但是我太菜了没搞出来qwq

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值