您的位置:首页 > 其它

ZOJ 3791 An Easy Game(DP)

2014-06-21 19:43 393 查看
题目链接

题意 : 给你两个长度为N的字符串,将第一个字符串每次只能变化M个,问变换K次之后变成第二个字符串一共有几种方法。

思路 : DP。dp[i][j]表示变了 i 次之后有j个不一样的字母的方法数。

状态转移方程:dp[i+1][j+M-2*k] += (dp[i][j]*(c[j][k]*c[N-j][M-k]) ;

c[j][k]表示的是从j个不匹配的字符中找出k个不匹配,所以c[N-j][M-k]表示的剩下的N-j个中挑出M-k个匹配的进行变换。两者相乘就是组合数,表明这次变换的方法数。

#include <stdio.h>
#include <string.h>
#include <iostream>

using namespace std ;

long long c[110][110],dp[110][110] ;
char sh[110],ch[110] ;

void cmn()
{
for(int i = 0 ; i < 110 ; i++)
c[i][0] = 1 ;
for(int i = 1 ; i < 110 ; i++)
{
for(int j = 1 ; j <= i ; j++)
c[i][j] = (c[i-1][j-1]+c[i-1][j])%1000000009 ;
}
}
int main()
{
int N,K,M ;
cmn() ;
while(~scanf("%d %d %d",&N,&K,&M))
{
scanf("%s %s",ch,sh) ;
int cnt = 0 ;
memset(dp,0,sizeof(dp)) ;
for(int i = 0 ; i < N ; i++)
if(sh[i] != ch[i])
cnt++ ;
dp[0][cnt] = 1 ;
for(int i = 0 ; i < K ; i++)
{
for(int j = 0 ; j <= N ; j++)
{
for(int k = 0 ; k <= M ; k++)
{
if(j+M-2*k < 0) break ;
if(j+M-2*k > N) continue ;
dp[i+1][j+M-2*k] += ((dp[i][j]%1000000009)*(c[j][k]*c[N-j][M-k]%1000000009))%1000000009 ;
}
}
}
printf("%lld\n",dp[K][0]) ;
}
return 0 ;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: