[ARC119F]AtCoder Express 3
Posted Tan_tan_tann
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ARC119F]AtCoder Express 3相关的知识,希望对你有一定的参考价值。
AtCoder Express 3
题解
求从
0
0
0到
n
n
n号点的方案数,我们应该很容易想到
d
p
dp
dp。
由于答案求的是最短路不超过
k
k
k的方案数,所以我们很容易想到将最短路加入状态中。
我们令
d
p
i
,
j
,
k
,
0
/
1
dp_{i,j,k,0/1}
dpi,j,k,0/1表示到点
i
i
i左边的第一个
A
A
A站台最短路为
j
j
j,到左边第一个
B
B
B最短路为
k
k
k,点
i
i
i为
A
/
B
A/B
A/B的方案数。
但很明显,如果直接这样
d
p
dp
dp一定是会超时的,光是找左边的第一个
A
/
B
A/B
A/B站台都会很困难。
我们考虑左边第一个站台
A
A
A与左边第一个站台
B
B
B有什么关系。
很明显,我们可以从左边第一个站台
A
A
A跳过
i
i
i,再往回跳一位到
B
B
B。
但这样的
B
B
B不一定在
i
i
i的左侧,但这并没有关系,我们可以将我们的
d
p
dp
dp改一改,
j
,
k
j,k
j,k表示到左边第一个
A
/
B
A/B
A/B站台及其右边的
A
/
B
A/B
A/B站台的最短路。
这样我们就可以将转移做到
O
(
1
)
O(1)
O(1)了。
此外我们还发现了一个性质,
∣
j
−
k
∣
⩽
2
\\left|j-k\\right|\\leqslant 2
∣j−k∣⩽2。
一旦超过了
2
2
2,我们就可以用上面的办法去使得它的最短路变得更小。
所以我们就没必要将
j
,
k
j,k
j,k全部记录下来了,我们就记录
j
,
Δ
j,\\Delta
j,Δ,使得
k
=
j
+
Δ
k=j+\\Delta
k=j+Δ。
这样,
d
p
dp
dp的时间复杂度就是
O
(
n
k
)
O\\left(nk\\right)
O(nk)了。
容易得到转移方程式,
d
p
i
,
j
,
min
(
d
+
1
,
2
)
,
0
+
=
d
p
i
−
1
,
j
,
d
,
0
dp_{i,j,\\min(d+1,2),0}+=dp_{i-1,j,d,0}
dpi,j,min(d+1,2),0+=dpi−1,j,d,0
d
p
i
,
j
,
min
(
d
+
1
,
1
)
,
0
+
=
d
p
i
−
1
,
j
,
d
,
1
dp_{i,j,\\min(d+1,1),0}+=dp_{i-1,j,d,1}
dpi,j,min(d+1,1),0+=dpi−1,j,d,1
d
p
i
,
j
+
min
(
d
−
1
,
−
1
)
,
max
(
d
−
1
,
−
1
)
,
1
+
=
d
p
i
−
1
,
j
,
d
,
0
dp_{i,j+\\min(d-1,-1),\\max(d-1,-1),1}+=dp_{i-1,j,d,0}
dpi,j+min(d−1,−1),max(d−1,−1),1+=dpi−1,j,d,0
d
p
i
,
j
+
min
(
d
,
1
)
,
max
(
d
−
1
,
−
2
)
,
1
+
=
d
p
i
−
1
,
j
,
d
,
1
dp_{i,j+\\min(d,1),\\max(d-1,-2),1}+=dp_{i-1,j,d,1}
dpi,j+min(d,1),max(d−1,−2),1+=dpi−1,j,d,1
跑一遍
d
p
dp
dp即可。
时间复杂度 O ( n k ) O\\left(nk\\right) O(nk)。
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 4005
#define lowbit(x) (x&-x)
#define reg register
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x7f7f7f7f;
const LL jzm=2333;
const int zero=2;
const int mo=1e9+7;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int n,k,typ[MAXN],dp[2][MAXN][5][2],ans;
char str[MAXN];
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
void Add(int &x,int y){x=add(x,y);}
signed main(){
read(n);read(k);scanf("%s",str+1);n--;
for(int i=1;i<=n;i++)if(str[i]=='A')typ[i]=1;else if(str[i]=='B')typ[i]=2;
if(typ[1]^1)dp[1][0][3][0]=1;if(typ[1]^2)dp[1][1][1][1]=1;
for(int i=2;i<=n;i++){
int now=i&1,las=now^1;
for(int j=0;j<k+2;j++)
for(int d=-2;d<=2;d++){
if(typ[i]^1){
if(dp[las][j][d+2][0])Add(dp[now][j][min(d+3,4)][0],dp[las][j][d+2][0]);
if(dp[las][j][d+2][1])Add(dp[now][j][min(d+3,3)][0],dp[las][j][d+2][1]);
}
if(typ[i]^2){
if(dp[las][j][d+2][0])Add(dp[now][j+min(d+1,1)][max(d+1,1)][1],dp[las][j][d+2][0]);
if(dp[las][j][d+2][1])Add(dp[now][j+min(d+2,1)][max(d+1,0)][1],dp[las][j][d+2][1]);
}
}
for(int j=0;j<k+2;j++)
for(int d=-2;d<=2;d++)
dp[las][j][d+2][0]=dp[las][j][d+2]<以上是关于[ARC119F]AtCoder Express 3的主要内容,如果未能解决你的问题,请参考以下文章