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;
}
posted @ 2018-10-09 19:42  lokiii  阅读(118)  评论(0编辑  收藏  举报