LGP3126题解

这道题还有点意思。

路径要求是一个回文串,回文串立马枚举中点。中点只可能在对角线上。

枚举对角线上的一个点,然后两边的路径必须完全相同。

既然路径上的字符必须完全相同,那么每个前缀也必须完全相同。

考虑 DP。设 \(dp[x1][y1][x2][y2]\) 表示左上方的路径终点在 \((x1,y1)\),右下方的路径终点在 \((x2,y2)\)

这状态看上去就可以优化,\(dp[k][x1][x2]\),表示 \((x1,k-x1)\)\((x2,k-x2)\)

然后随便转移一下就差不多了吧。

复杂度 \(O(n^3)\),可以通过。

需要注意滚动数组。

#include<cstdio>
typedef unsigned ui;
const ui M=505,mod=1e9+7;
ui n,dp[2][M][M];char q[M][M],p[M][M];
signed main(){
	ui ans(0);
	scanf("%u",&n);
	for(ui i=1;i<=n;++i)scanf("%s",q[i]+1);
	for(ui i=1;i<=n;++i)for(ui j=1;j<=n;++j)p[i][j]=q[n-i+1][n-j+1];
	if(q[1][1]!=p[1][1])return printf("0"),0;
	dp[0][1][1]=1;
	for(ui now(1),lst(0),i=3;i<=n+1;now^=lst^=now^=lst,++i){
		for(ui x1=1;x1<i;++x1)for(ui x2=1;x2<i;++x2)dp[now][x1][x2]=0;
		for(ui x1=1;x1<i;++x1){
			for(ui x2=1;x2<i;++x2)if(q[x1][i-x1]==p[x2][i-x2]){
				dp[now][x1][x2]=(dp[lst][x1][x2]+dp[lst][x1-1][x2]+dp[lst][x1][x2-1]+dp[lst][x1-1][x2-1])%mod;
			}
		}
	}
	for(ui i=1;i<=n;++i)ans=(ans+dp[n+1&1][i][n+1-i])%mod;
	printf("%u",ans);
}
posted @ 2022-03-15 12:00  Prean  阅读(24)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};