bzoj 1566: [NOI2009]管道取珠【dp】
想不出来想不出来
仔细考虑平方的含义,我们可以把它想成两个人同时操作,最后得到相同序列的情况
然后就比较简单了,设f[t][i][j]为放了t个珠子,A的上方管道到了第i颗珠子,B的上方管道到了第j颗珠子的方案数,转移的话直接看下一步的珠子颜色是否相同即可
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=505,mod=1024523;
int n,m,f[2][N][N];
char a[N],b[N];
void jia(int &x,int y)
{
x+=y;
if(x>=mod)
x-=mod;
}
int main()
{
scanf("%d%d%s%s",&n,&m,a+1,b+1);
reverse(a+1,a+1+n);
reverse(b+1,b+1+m);
f[0][0][0]=1;
for(int t=0;t<n+m;t++)
{
memset(f[~t&1],0,sizeof(f[~t&1]));
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
if(f[t&1][i][j])
{
if(a[i+1]==b[t-j+1])
jia(f[~t&1][i+1][j],f[t&1][i][j]);
if(a[j+1]==b[t-i+1])
jia(f[~t&1][i][j+1],f[t&1][i][j]);
if(a[i+1]==a[j+1])
jia(f[~t&1][i+1][j+1],f[t&1][i][j]);
if(b[t-i+1]==b[t-j+1])
jia(f[~t&1][i][j],f[t&1][i][j]);
}
}
printf("%d\n",f[(n+m)&1][n][n]);
return 0;
}