[ARC119F] AtCoder Express 3

题目链接

观察样例 1 的解释,发现切换类型的方法是比较单一的

这种就是直接走一段换一段,我们可以人为钦定换乘时最多走一步,因为相邻的同色也可以视作走车站

这种情况复杂一些,需要往回走一段,但是依然可以发现往回走也至多一步,因为如果走了两步说明往回走了一步到达的车站依然同色,那么走的车站必然不会是后面那一个

根据这两个性质,发现最短路的形态非常单一,只会从上一个红色或蓝色的车站转移过来,因此设 \(dp_{i,j,k,0/1}\) 表示考虑到第 \(i\) 个车站,上一个红色的车站的最短路为 \(j\),蓝色的为 \(k\),上一个车站为红 \(/\) 蓝色,转移时考虑如果上一步放红色车站,且这一步放红色车站,那么红色车站最短路更新为 \(j+1\),蓝色无法更新,如果放蓝色车站,那么红色车站最短路更新为 \(min(j,k+2)\),蓝色车站最短路更新为 \(min(j+1,k+1)\),上一步放红色车站是对称的

这样做的复杂度是 \(O(n^3)\),发现最短路更新时,仅当 \(|j-k|<2\) 时才可能无法确定最短路的更新,否则与 \(|j-k|=2\) 的情况是等价的,因此复杂度优化到 \(O(n^2)\)

点击查看代码
#include<bits/stdc++.h>
#define N 4005
using namespace std;
int read(){
	int w=0,h=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')h=-h;ch=getchar();}
	while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
	return w*h;
}
const int mod=1e9+7;
int n,m,ans,dp[N][N][6][2];char S[N];
int&DP(int i,int x,int y,int t){x=min(x,y+2);y=min(y,x+2);return dp[i][x][y-x+2][t];}
void add(int&x,int y){(x+=y)>=mod?x-=mod:x;}
signed main(){
	n=read();m=read();scanf("%s",S+1);
	dp[0][0][2][0]=1;
	for(int i=1;i<n;i++)
		for(int j=0;j<=i;j++)
			for(int k=j-2;k<=j+2;k++){
				if(S[i]=='A'||S[i]=='?'){
					add(DP(i,j+1,k,0),DP(i-1,j,k,0));
					add(DP(i,min(j+1,k+1),min(j+2,k),0),DP(i-1,j,k,1));
				}
				if(S[i]=='B'||S[i]=='?'){
					add(DP(i,j,k+1,1),DP(i-1,j,k,1));
					add(DP(i,min(j,k+2),min(j+1,k+1),1),DP(i-1,j,k,0));
				}
			}
	for(int i=0;i<=n;i++)
		for(int j=i-2;j<=i+2;j++)
			if(min(i,j)<m)add(ans,(DP(n-1,i,j,0)+DP(n-1,i,j,1))%mod);
	printf("%d\n",ans);
	return 0;
}

posted @ 2023-09-17 19:26  pidan007  阅读(11)  评论(0编辑  收藏  举报